feat: reusable badge templates, dynamic price and superscript cents, size/align/padding controls, fix saving
This commit is contained in:
1 parent
f9aa2297ba
commit
5a6788b593
6 files changed
+1196
-359
No files matched your search
+81
-40
@@ -1,5 +1,6 @@
|
||||
import { NewsletterCampaign, ProductItem } from '@/types/newsletter';
|
||||
import { SUPABASE_ASSETS_BASE } from './defaultCampaign';
|
||||
import { renderCleanBadgeSvg } from './badgeUtils';
|
||||
|
||||
export function renderEmailHtml(campaign: NewsletterCampaign): string {
|
||||
const renderedModules = campaign.modules.map((m) => renderModule(m, campaign)).join('\n');
|
||||
@@ -620,46 +621,86 @@ function renderExactProductCard(
|
||||
</tr>
|
||||
<tr height="1">
|
||||
<td style="padding: 0 8px 12px 8px; text-align: center;" valign="bottom">
|
||||
<!-- Vyladená Cenovka Premium v8/v11 1:1 alebo vyrenderovaná PNG cenovka z editora -->
|
||||
${p.customBadgePngUrl ? `
|
||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" align="center" style="margin: 0 auto;">
|
||||
<tr>
|
||||
<td align="center">
|
||||
<img src="${escapeHtml(p.customBadgePngUrl)}" width="110" alt="Cenovka" style="display: block; margin: 0 auto; max-width: 120px;">
|
||||
</td>
|
||||
</tr>
|
||||
</table>` : `
|
||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" align="center" style="width: 95px; margin: 0 auto;">
|
||||
<tr>
|
||||
<td align="center">
|
||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" style="background-color: ${badgeHdrBg}; border: 0; border-radius: 12px; box-shadow: 0 4px 10px rgba(0,0,0,0.18); width: 85px; overflow: hidden;">
|
||||
${badgeCustomTxt ? `
|
||||
<tr>
|
||||
<td bgcolor="${badgeHdrBg}" style="padding: 4px 4px; text-align: center; background-color: ${badgeHdrBg};">
|
||||
<span style="font-family: 'Arial Narrow', Arial, sans-serif; font-size: 10px; color: ${badgeHdrColor}; font-weight: 800; text-transform: uppercase;">${escapeHtml(badgeCustomTxt)}</span>
|
||||
</td>
|
||||
</tr>` : (p.discountText ? `
|
||||
<tr>
|
||||
<td style="padding: 2px 4px; text-align: right; background-color: ${badgeHdrBg};">
|
||||
<span style="font-family: 'Arial Narrow', Arial, sans-serif; font-size: 9px; color: ${badgeHdrColor}; font-weight: 700; text-transform: lowercase;">${escapeHtml(p.badgeText || 'zľava')}</span>
|
||||
<span style="font-family: 'Arial Narrow', Arial, sans-serif; font-size: 20px; color: ${badgeHdrColor}; font-weight: 900; line-height: 1; margin-left: 2px;">${escapeHtml(p.discountText)}</span>
|
||||
</td>
|
||||
</tr>` : '')}
|
||||
<tr>
|
||||
<td class="force-text-white" bgcolor="${badgePrcBg}" style="background-color: ${badgePrcBg}; padding: 4px 2px 2px 2px; font-family: 'Arial Narrow', Arial, sans-serif; color: ${badgePrcColor}; font-weight: 900; line-height: 1; text-align: center; border-radius: 0 0 12px 12px;">
|
||||
<span style="font-size: 52px;">${escapeHtml(p.priceMain)}</span><sup style="font-size: 26px; vertical-align: top; line-height: 1.2;">${escapeHtml(p.priceSub)}</sup>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
${p.showSlovakFlag ? `
|
||||
<tr>
|
||||
<td align="right" style="line-height: 0; padding: 0;">
|
||||
<img src="${SUPABASE_ASSETS_BASE}vlajka_srdce.png" width="40" alt="SK" style="display: block; margin-top: -26px; margin-right: -10px; padding: 4px; filter: drop-shadow(1px 0 0 #fefefe) drop-shadow(-1px 0 0 #fefefe) drop-shadow(0 1px 0 #fefefe) drop-shadow(0 -1px 0 #fefefe);">
|
||||
</td>
|
||||
</tr>` : ''}
|
||||
</table>`}
|
||||
${(() => {
|
||||
const bWidth = p.badgeWidth || (p.badgeCustomTemplate ? (p.badgeCustomTemplate.width || 110) : 95);
|
||||
const bAlign = p.badgeAlign || (p.badgeCustomTemplate ? (p.badgeCustomTemplate.align || 'center') : 'center');
|
||||
const padTop = p.badgePaddingTop ?? (p.badgeCustomTemplate?.paddingTop ?? 0);
|
||||
const padBottom = p.badgePaddingBottom ?? (p.badgeCustomTemplate?.paddingBottom ?? 0);
|
||||
|
||||
let marginStyle = 'margin: 0 auto;';
|
||||
if (bAlign === 'left') {
|
||||
marginStyle = 'margin: 0 auto 0 0; margin-right: auto; margin-left: 0;';
|
||||
} else if (bAlign === 'right') {
|
||||
marginStyle = 'margin: 0 0 0 auto; margin-left: auto; margin-right: 0;';
|
||||
}
|
||||
|
||||
// 1. Ak produkt má vlastnú dynamickú šablónu cenovky (čistý SVG vektor bez editovacích prvkov a so živou cenou)
|
||||
if (p.badgeCustomTemplate) {
|
||||
return `
|
||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" align="${bAlign}" style="${marginStyle} width: ${bWidth}px; padding-top: ${padTop}px; padding-bottom: ${padBottom}px;">
|
||||
<tr>
|
||||
<td align="${bAlign}">
|
||||
${renderCleanBadgeSvg(p.badgeCustomTemplate, p, bWidth)}
|
||||
</td>
|
||||
</tr>
|
||||
${p.showSlovakFlag ? `
|
||||
<tr>
|
||||
<td align="right" style="line-height: 0; padding: 0;">
|
||||
<img src="${SUPABASE_ASSETS_BASE}vlajka_srdce.png" width="40" alt="SK" style="display: block; margin-top: -26px; margin-right: -10px; padding: 4px; filter: drop-shadow(1px 0 0 #fefefe) drop-shadow(-1px 0 0 #fefefe) drop-shadow(0 1px 0 #fefefe) drop-shadow(0 -1px 0 #fefefe);">
|
||||
</td>
|
||||
</tr>` : ''}
|
||||
</table>`;
|
||||
}
|
||||
|
||||
// 2. Ak je nahraná statická PNG cenovka
|
||||
if (p.customBadgePngUrl) {
|
||||
return `
|
||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" align="${bAlign}" style="${marginStyle} width: ${bWidth}px; padding-top: ${padTop}px; padding-bottom: ${padBottom}px;">
|
||||
<tr>
|
||||
<td align="${bAlign}">
|
||||
<img src="${escapeHtml(p.customBadgePngUrl)}" width="${bWidth}" alt="Cenovka" style="display: block; width: 100%; max-width: ${bWidth}px; margin: 0 auto;">
|
||||
</td>
|
||||
</tr>
|
||||
</table>`;
|
||||
}
|
||||
|
||||
// 3. Predvolená COOP cenovka s plnou podporou šírky, zarovnania a odsadenia
|
||||
const mainFontSize = Math.max(28, Math.round(bWidth * 0.54));
|
||||
const subFontSize = Math.max(14, Math.round(bWidth * 0.27));
|
||||
|
||||
return `
|
||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" align="${bAlign}" style="${marginStyle} width: ${bWidth}px; padding-top: ${padTop}px; padding-bottom: ${padBottom}px;">
|
||||
<tr>
|
||||
<td align="${bAlign}">
|
||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" style="background-color: ${badgeHdrBg}; border: 0; border-radius: 12px; box-shadow: 0 4px 10px rgba(0,0,0,0.18); width: ${bWidth}px; overflow: hidden;">
|
||||
${badgeCustomTxt ? `
|
||||
<tr>
|
||||
<td bgcolor="${badgeHdrBg}" style="padding: 4px 4px; text-align: center; background-color: ${badgeHdrBg};">
|
||||
<span style="font-family: 'Arial Narrow', Arial, sans-serif; font-size: 10px; color: ${badgeHdrColor}; font-weight: 800; text-transform: uppercase;">${escapeHtml(badgeCustomTxt)}</span>
|
||||
</td>
|
||||
</tr>` : (p.discountText ? `
|
||||
<tr>
|
||||
<td style="padding: 2px 4px; text-align: right; background-color: ${badgeHdrBg};">
|
||||
<span style="font-family: 'Arial Narrow', Arial, sans-serif; font-size: 9px; color: ${badgeHdrColor}; font-weight: 700; text-transform: lowercase;">${escapeHtml(p.badgeText || 'zľava')}</span>
|
||||
<span style="font-family: 'Arial Narrow', Arial, sans-serif; font-size: 20px; color: ${badgeHdrColor}; font-weight: 900; line-height: 1; margin-left: 2px;">${escapeHtml(p.discountText)}</span>
|
||||
</td>
|
||||
</tr>` : '')}
|
||||
<tr>
|
||||
<td class="force-text-white" bgcolor="${badgePrcBg}" style="background-color: ${badgePrcBg}; padding: 4px 2px 2px 2px; font-family: 'Arial Narrow', Arial, sans-serif; color: ${badgePrcColor}; font-weight: 900; line-height: 1; text-align: center; border-radius: 0 0 12px 12px;">
|
||||
<span style="font-size: ${mainFontSize}px;">${escapeHtml(p.priceMain)}</span><sup style="font-size: ${subFontSize}px; vertical-align: top; line-height: 1.2;">${escapeHtml(p.priceSub)}</sup>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
${p.showSlovakFlag ? `
|
||||
<tr>
|
||||
<td align="right" style="line-height: 0; padding: 0;">
|
||||
<img src="${SUPABASE_ASSETS_BASE}vlajka_srdce.png" width="40" alt="SK" style="display: block; margin-top: -26px; margin-right: -10px; padding: 4px; filter: drop-shadow(1px 0 0 #fefefe) drop-shadow(-1px 0 0 #fefefe) drop-shadow(0 1px 0 #fefefe) drop-shadow(0 -1px 0 #fefefe);">
|
||||
</td>
|
||||
</tr>` : ''}
|
||||
</table>`;
|
||||
})()}
|
||||
${p.unitPrice ? `<div style="font-size: 9px; color: #666666; margin-top: 4px; font-weight: 500; font-family: Arial, sans-serif;">${escapeHtml(p.unitPrice)}</div>` : ''}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
Reference in new issue
Block a user