import { NewsletterCampaign, ProductItem } from '@/types/newsletter';
import { SUPABASE_ASSETS_BASE } from './defaultCampaign';
import { renderCleanBadgeSvg } from './badgeUtils';
import { pickAlt } from './altText';
export function renderEmailHtml(campaign: NewsletterCampaign): string {
const renderedModules = campaign.modules.map((m) => renderModule(m, campaign)).join('\n');
return `
${escapeHtml(campaign.title)}
${escapeHtml(campaign.preheader || '')}
͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏
`;
}
export function renderSingleModuleHtml(m: any, campaign: NewsletterCampaign): string {
return renderModule(m, campaign);
}
function renderModule(m: any, campaign: NewsletterCampaign): string {
switch (m.type) {
case 'announcement':
if (m.data?.enabled === false) {
return '';
}
return `
|
${escapeHtml(m.data.tipBadge || 'TIP')}
${escapeHtml(m.data.text || '')}
${m.data.linkText ? `
` : ''}
|
|
`;
case 'header':
const rawNav = m.data.navLinks && m.data.navLinks.length > 0 ? m.data.navLinks : [
{ label: 'Letáky', url: 'https://www.coop.sk/sk/letaky', variant: 'outline' },
{ label: 'COOP Klub', url: 'https://www.coopklub.sk', variant: 'filled' }
];
const navLinks = rawNav.map((link: any) => {
if (link.variant === 'filled') {
return ``;
}
return ``;
}).join('\n');
return `
`;
case 'banner':
return `
|
${m.data.title || m.data.description || m.data.buttonText ? `
${m.data.title ? `${escapeHtml(m.data.title)}` : ''}
${m.data.description ? `${escapeHtml(m.data.description)} ` : ''}
${m.data.buttonText ? `
` : ''}
|
` : ''}
`;
case 'products_grid':
const globalValidity = m.data.globalValidity || '';
const products: ProductItem[] = m.data.products || [];
const cardBg = m.data.cardBgColor || '#feeaea';
const cardBorder = m.data.cardBorderColor || '#f5d4d4';
const badgeHdrBg = m.data.badgeHeaderBg || '#fefefe';
const badgeHdrColor = m.data.badgeHeaderColor || '#000000';
const badgePrcBg = m.data.badgePriceBg || '#e2001a';
const badgePrcColor = m.data.badgePriceColor || '#fefefe';
const badgeCustomTxt = m.data.badgeHeaderCustomText || null;
const cols = m.data.columns === 1 ? 1 : 2;
const rows: ProductItem[][] = [];
for (let i = 0; i < products.length; i += cols) {
rows.push(products.slice(i, i + cols));
}
const rowsHtml = rows.map((row) => {
if (cols === 1) {
const p = row[0];
return `
|
${renderExactProductCard(p, globalValidity, cardBg, cardBorder, badgeHdrBg, badgeHdrColor, badgePrcBg, badgePrcColor, badgeCustomTxt, m.data.sectionTitle)}
|
`;
}
return `
${row.map((p, idx) => `
|
${renderExactProductCard(p, globalValidity, cardBg, cardBorder, badgeHdrBg, badgeHdrColor, badgePrcBg, badgePrcColor, badgeCustomTxt, m.data.sectionTitle)}
| `).join('\n')}
${row.length === 1 ? ' | ' : ''}
`;
}).join('\n');
return `
${m.data.sectionTitle ? `
${escapeHtml(m.data.sectionTitle)}
|
` : ''}
|
${rowsHtml}
|
`;
case 'loyalty_club':
if (m.data.enabled === false) {
return '';
}
const lProducts = m.data.products || [];
return `
${escapeHtml(m.data.sectionTitle || 'Vernostné zľavy')}
|
|
|
${lProducts.map((p: any, idx: number) => `
|
${renderExactLoyaltyCard(p, m.data.globalValidity || '2. 5. – 15. 5. 2026')}
| `).join('\n')}
|
`;
case 'articles_row':
const it1 = m.data.item1;
const it2 = m.data.item2;
// Ak ide o letáky
if (it1?.btnText) {
return `
`;
}
// Inak články / recepty
return `
`;
case 'footer':
return `
`;
default:
return '';
}
}
function renderExactProductCard(
p: ProductItem,
globalValidity: string,
cardBg: string,
cardBorder: string,
badgeHdrBg: string,
badgeHdrColor: string,
badgePrcBg: string,
badgePrcColor: string,
badgeCustomTxt: string | null,
sectionTitle?: string
): string {
const validity = p.validityOverride || globalValidity;
const effectiveCardBg = p.cardBgColor || cardBg || '#feeaea';
const storesHtml = `
${p.stores?.potraviny ? ` |
` : ''}
${p.stores?.supermarket ? ` |
` : ''}
${p.stores?.tempo ? ` |
` : ''}
`;
const badgeLayout = p.badgeLayout || 'below';
// Pomocná funkcia na render samotnej cenovky (bez obalového )
const renderBadgeContent = (bWidth: number, bAlign: string, padTop: number, padBottom: number, marginStyle: string) => {
// Vlastná PNG cenovka (výnimka) má prednosť pred šablónou; po jej odstránení sa vráti šablóna
if (p.customBadgePngUrl) {
return `
`;
}
if (p.badgeCustomTemplate) {
return `
|
${renderCleanBadgeSvg(p.badgeCustomTemplate, p, bWidth)}
|
`;
}
const mainFontSize = Math.max(28, Math.round(bWidth * 0.54));
const subFontSize = Math.max(14, Math.round(bWidth * 0.27));
return `
${badgeCustomTxt ? `
|
${escapeHtml(badgeCustomTxt)}
|
` : (p.discountText ? `
|
${escapeHtml(p.badgeText || 'zľava')}
${escapeHtml(p.discountText)}
|
` : '')}
|
${escapeHtml(p.priceMain)}${escapeHtml(p.priceSub)}
|
|
`;
};
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 `
| ${escapeHtml(validity)} |
${storesHtml} |
|
|
${renderBadgeContent(bWidth, bAlign, padTop, padBottom, marginStyle)}
${p.unitPrice ? ` ${escapeHtml(p.unitPrice)} ` : ''}
|
${escapeHtml(p.title)}
|
`;
}
// Predvolené rozloženie: cenovka pod obrázkom
return `
| ${escapeHtml(validity)} |
${storesHtml} |
|
|
${escapeHtml(p.title)}
|
|
${(() => {
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;';
}
return renderBadgeContent(bWidth, bAlign, padTop, padBottom, marginStyle);
})()}
|
|
${p.unitPrice ? ` ${escapeHtml(p.unitPrice)} ` : ' '}
|
`;
}
function renderExactLoyaltyCard(p: any, validity: string): string {
const cardValidity = p.validityOverride || validity;
const storesHtml = `
${p.stores?.potraviny ? ` | ` : ''}
${p.stores?.supermarket ? ` | ` : ''}
${p.stores?.tempo ? ` | ` : ''}
`;
const loyaltyBg = p.cardBgColor || '#e6e1d9';
return `
| ${escapeHtml(cardValidity)} |
${storesHtml} |
|
|
${escapeHtml(p.title)}
|
${(() => {
// 1. Ak má vernostný produkt vlastnú PNG cenovku (prednosť) alebo dynamickú šablónu cenovky
if (p.customBadgePngUrl || p.badgeCustomTemplate) {
const bWidth = p.badgeWidth || p.badgeCustomTemplate?.width || 120;
const bAlign = p.badgeAlign || p.badgeCustomTemplate?.align || '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;';
}
const loyaltyProductData = {
priceMain: p.cardPriceMain || p.priceMain || '0',
priceSub: p.cardPriceSub || p.priceSub || '00',
discountText: p.cardDiscount || p.discountText || '',
unitPrice: p.cardUnitPrice || p.unitPrice || '',
cardPriceMain: p.cardPriceMain,
cardPriceSub: p.cardPriceSub,
cardDiscount: p.cardDiscount
};
return `
${p.customBadgePngUrl
? ` `
: renderCleanBadgeSvg(p.badgeCustomTemplate, loyaltyProductData, bWidth)}
|
`;
}
// 2. Predvolený Dual Sticker Block (Bez karty / S kartou) 1:1
return `
|
Bez karty
zľava ${escapeHtml(p.noCardDiscount)}
|
|
${escapeHtml(p.noCardPriceMain)}${escapeHtml(p.noCardPriceSub)}
|
|
|
S kartou
zľava
${escapeHtml(p.cardDiscount)}
|
|
${escapeHtml(p.cardPriceMain)}${escapeHtml(p.cardPriceSub)}
|
|
|
|
${escapeHtml(p.noCardUnitPrice)}
|
${escapeHtml(p.cardUnitPrice)}
|
`;
})()}
|
${p.badgeCustomTemplate || p.customBadgePngUrl ? `
|
${p.cardUnitPrice || p.unitPrice ? ` ${escapeHtml(p.cardUnitPrice || p.unitPrice)} ` : ' '}
|
` : ''}
`;
}
function escapeHtml(str: string): string {
if (!str) return '';
return String(str)
.replace(/&/g, '&')
.replace(//g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
|