feat: moznost pozicovania cenovky vedla produktu (uloha 8)

This commit is contained in:
Jakub_Hostacny committed 2026-10-08 10:15:39 +02:00
1 parent a82c2d5af8
commit 0aa664b08b
3 files changed
+169 -56

No files matched your search

+92 -56
View File
@@ -637,6 +637,97 @@ function renderExactProductCard(
${p.stores?.tempo ? `<tr><td align="right" style="line-height: 0;"><table role="presentation" cellspacing="0" cellpadding="0" border="0" align="right"><tr><td style="border: 0; background-color: #005239; padding: 0; line-height: 0;"><img src="${SUPABASE_ASSETS_BASE}stit_tempo.png" height="10" alt="Tempo" style="display: block; height: 10px; width: auto; border: 0;"></td></tr></table></td></tr>` : ''}
</table>`;
const badgeLayout = p.badgeLayout || 'below';
// Pomocná funkcia na render samotnej cenovky (bez obalového <td>)
const renderBadgeContent = (bWidth: number, bAlign: string, padTop: number, padBottom: number, marginStyle: string) => {
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>
</table>`;
}
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="${escapeHtml(p.title || 'Cenovka')}" style="display: block; width: 100%; max-width: ${bWidth}px; margin: 0 auto;">
</td>
</tr>
</table>`;
}
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>
</table>`;
};
if (badgeLayout === 'side') {
// Rozloženie: obrázok vľavo | cenovka vpravo
const bWidth = p.badgeWidth || (p.badgeCustomTemplate ? (p.badgeCustomTemplate.width || 110) : 95);
const bAlign = 'center';
const padTop = p.badgePaddingTop ?? (p.badgeCustomTemplate?.paddingTop ?? 0);
const padBottom = p.badgePaddingBottom ?? (p.badgeCustomTemplate?.paddingBottom ?? 0);
const marginStyle = 'margin: 0 auto;';
return `
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%" height="100%" class="glass-product" bgcolor="${effectiveCardBg}" style="background-color: ${effectiveCardBg}; border: 0; border-radius: 16px; box-shadow: 0 4px 15px rgba(0, 0, 0, 0.15); height: 100%; min-height: 100%;">
<tr height="1">
<td colspan="2" style="padding: 15px 15px 0 15px; height: 1px;" valign="top">
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
<tr>
<td style="font-size: 9px; color: #666666; font-weight: 500;" valign="top">${escapeHtml(validity)}</td>
<td align="right">${storesHtml}</td>
</tr>
</table>
</td>
</tr>
<tr>
<td width="58%" height="160" style="padding: 8px 4px 8px 8px; text-align: center; height: 160px;" valign="middle">
<img src="${escapeHtml(p.imageUrl)}" width="180" alt="${escapeHtml(p.title || sectionTitle || 'Produkt')}" style="display: block; width: 100%; max-width: 180px; margin: 0 auto; border-radius: 8px;">
</td>
<td width="42%" style="padding: 8px 8px 8px 4px; text-align: center;" valign="middle">
${renderBadgeContent(bWidth, bAlign, padTop, padBottom, marginStyle)}
${p.unitPrice ? `<div style="font-size: 8px; color: #666666; font-weight: 500; font-family: Arial, sans-serif; text-align: center; margin-top: 4px;">${escapeHtml(p.unitPrice)}</div>` : ''}
</td>
</tr>
<tr>
<td colspan="2" height="54" style="padding: 0 8px 10px 8px; text-align: center; height: 54px; min-height: 54px;" valign="top">
<h3 class="force-text-dark" style="margin: 0; font-size: 15px; color: #1a1a1a; font-weight: 600; line-height: 1.25;">${escapeHtml(p.title)}</h3>
</td>
</tr>
</table>`;
}
// Predvolené rozloženie: cenovka pod obrázkom
return `
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%" height="100%" class="glass-product" bgcolor="${effectiveCardBg}" style="background-color: ${effectiveCardBg}; border: 0; border-radius: 16px; box-shadow: 0 4px 15px rgba(0, 0, 0, 0.15); height: 100%; min-height: 100%;">
<tr height="1">
@@ -666,68 +757,13 @@ function renderExactProductCard(
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>
</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="${escapeHtml(p.title || '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>
</table>`;
return renderBadgeContent(bWidth, bAlign, padTop, padBottom, marginStyle);
})()}
</td>
</tr>