feat: zmena farby pozadia produktov a editovatelne nazvy modulov
This commit is contained in:
1 parent
4e4e5e5af3
commit
00d681bec2
7 files changed
+325
-87
No files matched your search
@@ -63,8 +63,8 @@ export async function POST(req: NextRequest) {
|
||||
success: true,
|
||||
updated: true,
|
||||
campaignId: Number(existingCampaignId),
|
||||
brevoUrl: 'https://app.brevo.com/campaigns',
|
||||
brevoListingUrl: 'https://app.brevo.com/campaigns',
|
||||
brevoUrl: 'https://app.brevo.com/campaigns/listing',
|
||||
brevoListingUrl: 'https://app.brevo.com/campaigns/listing',
|
||||
message: 'Kampaň bola úspešne aktualizovaná v Brevo!'
|
||||
});
|
||||
}
|
||||
@@ -113,8 +113,8 @@ export async function POST(req: NextRequest) {
|
||||
success: true,
|
||||
updated: false,
|
||||
campaignId: data.id,
|
||||
brevoUrl: 'https://app.brevo.com/campaigns',
|
||||
brevoListingUrl: 'https://app.brevo.com/campaigns',
|
||||
brevoUrl: 'https://app.brevo.com/campaigns/listing',
|
||||
brevoListingUrl: 'https://app.brevo.com/campaigns/listing',
|
||||
message: 'Kampaň bola úspešne vytvorená v Brevo!'
|
||||
});
|
||||
} catch (error: any) {
|
||||
|
||||
@@ -51,8 +51,8 @@ export async function GET(req: NextRequest) {
|
||||
name: data.name,
|
||||
status: data.status,
|
||||
subject: data.subject,
|
||||
brevoUrl: 'https://app.brevo.com/campaigns',
|
||||
brevoListingUrl: 'https://app.brevo.com/campaigns'
|
||||
brevoUrl: 'https://app.brevo.com/campaigns/listing',
|
||||
brevoListingUrl: 'https://app.brevo.com/campaigns/listing'
|
||||
});
|
||||
} catch (err: any) {
|
||||
console.error('Brevo verify error:', err);
|
||||
|
||||
+1
-1
@@ -144,7 +144,7 @@ export default function Home() {
|
||||
modules: enforceAnchors(dbItem.data.modules)
|
||||
});
|
||||
if (dbItem.brevo_campaign_id) {
|
||||
setBrevoUrl('https://app.brevo.com/campaigns');
|
||||
setBrevoUrl('https://app.brevo.com/campaigns/listing');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,19 @@
|
||||
|
||||
import React from 'react';
|
||||
import { NewsletterModule, ProductItem, BadgeTemplate } from '@/types/newsletter';
|
||||
import { Plus, Trash2, Image as ImageIcon, Tag, Store, Globe } from 'lucide-react';
|
||||
import { Plus, Trash2, Image as ImageIcon, Tag, Store, Globe, Palette, Check } from 'lucide-react';
|
||||
import { SUPABASE_ASSETS_BASE } from '@/lib/defaultCampaign';
|
||||
import { ImageUploadInput } from './ImageUploadInput';
|
||||
|
||||
const PRODUCT_BG_PRESETS = [
|
||||
{ label: 'Červená', sub: 'Fantasticky', color: '#feeaea', border: '#f5d4d4' },
|
||||
{ label: 'Žltá', sub: 'Domáce', color: '#fef0c7', border: '#e6d49a' },
|
||||
{ label: 'Hnedá', sub: 'Gril', color: '#dcb085', border: '#c49a6c' },
|
||||
{ label: 'Sivá', sub: 'Neutrálna', color: '#e6e1d9', border: '#d5cfc5' },
|
||||
{ label: 'Zelená', sub: 'Bio', color: '#e8f5e9', border: '#c8e6c9' },
|
||||
{ label: 'Biela', sub: 'Čistá', color: '#ffffff', border: '#e5e7eb' },
|
||||
];
|
||||
|
||||
interface ConfigPanelProps {
|
||||
module: NewsletterModule | null;
|
||||
onUpdateModule: (updated: NewsletterModule) => void;
|
||||
@@ -40,11 +49,20 @@ export const ConfigPanel: React.FC<ConfigPanelProps> = ({
|
||||
|
||||
return (
|
||||
<div className="h-full overflow-y-auto p-5 space-y-6 bg-white border-l border-gray-200">
|
||||
<div className="border-b border-gray-100 pb-3">
|
||||
<span className="text-[10px] font-bold uppercase tracking-wider text-red-600 bg-red-50 px-2 py-0.5 rounded">
|
||||
{module.type}
|
||||
</span>
|
||||
<h2 className="text-base font-bold text-gray-900 mt-1">{module.title}</h2>
|
||||
<div className="border-b border-gray-100 pb-3 space-y-1.5">
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-[10px] font-bold uppercase tracking-wider text-red-600 bg-red-50 px-2 py-0.5 rounded">
|
||||
{module.type}
|
||||
</span>
|
||||
<span className="text-[10px] text-gray-400 font-medium">Názov modulu v editore</span>
|
||||
</div>
|
||||
<input
|
||||
type="text"
|
||||
value={module.title}
|
||||
onChange={(e) => onUpdateModule({ ...module, title: e.target.value })}
|
||||
placeholder="Názov modulu..."
|
||||
className="w-full text-base font-bold text-gray-900 border border-gray-200 hover:border-gray-300 focus:border-red-500 rounded-lg px-2.5 py-1.5 bg-gray-50/50 hover:bg-white focus:bg-white focus:outline-none focus:ring-1 focus:ring-red-500 transition-all"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* TOP ANNOUNCEMENT */}
|
||||
@@ -307,6 +325,99 @@ export const ConfigPanel: React.FC<ConfigPanelProps> = ({
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Farba pozadia skupiny produktov */}
|
||||
<div className="bg-gray-50 p-3.5 rounded-xl border border-gray-200 space-y-2.5">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-1.5">
|
||||
<Palette className="w-3.5 h-3.5 text-gray-700" />
|
||||
<label className="text-xs font-bold text-gray-800">Farba pozadia produktov</label>
|
||||
</div>
|
||||
<span className="text-[10px] font-mono font-bold px-1.5 py-0.5 bg-white border border-gray-200 rounded text-gray-700 uppercase">
|
||||
{module.data.cardBgColor || '#feeaea'}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Rýchle predvoľby */}
|
||||
<div className="grid grid-cols-3 gap-1.5">
|
||||
{PRODUCT_BG_PRESETS.map((preset) => {
|
||||
const currentBg = (module.data.cardBgColor || '#feeaea').toLowerCase();
|
||||
const isSelected = currentBg === preset.color.toLowerCase();
|
||||
return (
|
||||
<button
|
||||
key={preset.color}
|
||||
type="button"
|
||||
onClick={() => {
|
||||
const newColor = preset.color;
|
||||
const newBorder = preset.border;
|
||||
const updatedProducts = (module.data.products || []).map((p: ProductItem) => ({
|
||||
...p,
|
||||
cardBgColor: newColor,
|
||||
}));
|
||||
updateData({
|
||||
cardBgColor: newColor,
|
||||
cardBorderColor: newBorder,
|
||||
products: updatedProducts,
|
||||
});
|
||||
}}
|
||||
className={`flex items-center gap-1.5 px-2 py-1.5 rounded-lg border text-[11px] font-medium transition-all text-left ${
|
||||
isSelected
|
||||
? 'border-red-600 bg-white shadow-xs ring-1 ring-red-500 font-bold'
|
||||
: 'border-gray-200 bg-white hover:border-gray-300 text-gray-700'
|
||||
}`}
|
||||
>
|
||||
<span
|
||||
className="w-3.5 h-3.5 rounded-full border border-black/15 shrink-0 flex items-center justify-center"
|
||||
style={{ backgroundColor: preset.color }}
|
||||
>
|
||||
{isSelected && <Check className="w-2.5 h-2.5 text-gray-800" />}
|
||||
</span>
|
||||
<span className="truncate">{preset.label}</span>
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* Vlastná farba (Color Picker + HEX input) */}
|
||||
<div className="flex items-center gap-2 pt-2 border-t border-gray-200">
|
||||
<span className="text-[10px] text-gray-500 font-semibold shrink-0">Vlastná:</span>
|
||||
<div className="flex items-center gap-1.5 flex-1">
|
||||
<input
|
||||
type="color"
|
||||
value={module.data.cardBgColor || '#feeaea'}
|
||||
onChange={(e) => {
|
||||
const newColor = e.target.value;
|
||||
const updatedProducts = (module.data.products || []).map((p: ProductItem) => ({
|
||||
...p,
|
||||
cardBgColor: newColor,
|
||||
}));
|
||||
updateData({
|
||||
cardBgColor: newColor,
|
||||
products: updatedProducts,
|
||||
});
|
||||
}}
|
||||
className="w-7 h-7 rounded border border-gray-300 cursor-pointer p-0.5 bg-white shrink-0"
|
||||
/>
|
||||
<input
|
||||
type="text"
|
||||
value={module.data.cardBgColor || '#feeaea'}
|
||||
onChange={(e) => {
|
||||
const newColor = e.target.value;
|
||||
const updatedProducts = (module.data.products || []).map((p: ProductItem) => ({
|
||||
...p,
|
||||
cardBgColor: newColor,
|
||||
}));
|
||||
updateData({
|
||||
cardBgColor: newColor,
|
||||
products: updatedProducts,
|
||||
});
|
||||
}}
|
||||
placeholder="#feeaea"
|
||||
className="w-full text-xs font-mono border border-gray-300 rounded px-2 py-1 bg-white uppercase text-gray-800 font-bold"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Zoznam produktov */}
|
||||
<div className="space-y-4 pt-2">
|
||||
<div className="flex items-center justify-between">
|
||||
@@ -324,7 +435,7 @@ export const ConfigPanel: React.FC<ConfigPanelProps> = ({
|
||||
unitPrice: '1kg = 4,99 €',
|
||||
discountText: '20%',
|
||||
badgeText: 'zľava',
|
||||
cardBgColor: '#feeaea',
|
||||
cardBgColor: module.data.cardBgColor || '#feeaea',
|
||||
stores: { potraviny: true, supermarket: true, tempo: true }
|
||||
};
|
||||
updateData({ products: [...(module.data.products || []), newP] });
|
||||
@@ -791,6 +902,97 @@ export const ConfigPanel: React.FC<ConfigPanelProps> = ({
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Farba pozadia vernostných kariet */}
|
||||
<div className="bg-gray-50 p-3.5 rounded-xl border border-gray-200 space-y-2.5">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-1.5">
|
||||
<Palette className="w-3.5 h-3.5 text-gray-700" />
|
||||
<label className="text-xs font-bold text-gray-800">Farba pozadia produktov</label>
|
||||
</div>
|
||||
<span className="text-[10px] font-mono font-bold px-1.5 py-0.5 bg-white border border-gray-200 rounded text-gray-700 uppercase">
|
||||
{module.data.cardBgColor || '#e6e1d9'}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Rýchle predvoľby */}
|
||||
<div className="grid grid-cols-3 gap-1.5">
|
||||
{PRODUCT_BG_PRESETS.map((preset) => {
|
||||
const currentBg = (module.data.cardBgColor || '#e6e1d9').toLowerCase();
|
||||
const isSelected = currentBg === preset.color.toLowerCase();
|
||||
return (
|
||||
<button
|
||||
key={preset.color}
|
||||
type="button"
|
||||
onClick={() => {
|
||||
const newColor = preset.color;
|
||||
const updatedProducts = (module.data.products || []).map((p: any) => ({
|
||||
...p,
|
||||
cardBgColor: newColor,
|
||||
}));
|
||||
updateData({
|
||||
cardBgColor: newColor,
|
||||
products: updatedProducts,
|
||||
});
|
||||
}}
|
||||
className={`flex items-center gap-1.5 px-2 py-1.5 rounded-lg border text-[11px] font-medium transition-all text-left ${
|
||||
isSelected
|
||||
? 'border-red-600 bg-white shadow-xs ring-1 ring-red-500 font-bold'
|
||||
: 'border-gray-200 bg-white hover:border-gray-300 text-gray-700'
|
||||
}`}
|
||||
>
|
||||
<span
|
||||
className="w-3.5 h-3.5 rounded-full border border-black/15 shrink-0 flex items-center justify-center"
|
||||
style={{ backgroundColor: preset.color }}
|
||||
>
|
||||
{isSelected && <Check className="w-2.5 h-2.5 text-gray-800" />}
|
||||
</span>
|
||||
<span className="truncate">{preset.label}</span>
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* Vlastná farba (Color Picker + HEX input) */}
|
||||
<div className="flex items-center gap-2 pt-2 border-t border-gray-200">
|
||||
<span className="text-[10px] text-gray-500 font-semibold shrink-0">Vlastná:</span>
|
||||
<div className="flex items-center gap-1.5 flex-1">
|
||||
<input
|
||||
type="color"
|
||||
value={module.data.cardBgColor || '#e6e1d9'}
|
||||
onChange={(e) => {
|
||||
const newColor = e.target.value;
|
||||
const updatedProducts = (module.data.products || []).map((p: any) => ({
|
||||
...p,
|
||||
cardBgColor: newColor,
|
||||
}));
|
||||
updateData({
|
||||
cardBgColor: newColor,
|
||||
products: updatedProducts,
|
||||
});
|
||||
}}
|
||||
className="w-7 h-7 rounded border border-gray-300 cursor-pointer p-0.5 bg-white shrink-0"
|
||||
/>
|
||||
<input
|
||||
type="text"
|
||||
value={module.data.cardBgColor || '#e6e1d9'}
|
||||
onChange={(e) => {
|
||||
const newColor = e.target.value;
|
||||
const updatedProducts = (module.data.products || []).map((p: any) => ({
|
||||
...p,
|
||||
cardBgColor: newColor,
|
||||
}));
|
||||
updateData({
|
||||
cardBgColor: newColor,
|
||||
products: updatedProducts,
|
||||
});
|
||||
}}
|
||||
placeholder="#e6e1d9"
|
||||
className="w-full text-xs font-mono border border-gray-300 rounded px-2 py-1 bg-white uppercase text-gray-800 font-bold"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 2 Vernostné produkty */}
|
||||
<div className="space-y-4 pt-2">
|
||||
<span className="text-xs font-bold text-gray-800 uppercase tracking-wider block">
|
||||
|
||||
@@ -212,9 +212,9 @@ export const TopBar: React.FC<TopBarProps> = ({
|
||||
) : isVerifiedInBrevo && campaign.brevoCampaignId ? (
|
||||
/* Kampaň je overená priamo v Brevo: Ponúkame úpravu, aktualizáciu alebo odoslanie ako novú */
|
||||
<div className="flex items-center gap-1.5 bg-emerald-50 border border-emerald-200 p-1 rounded-xl">
|
||||
{/* Odkaz na úpravu v Brevo */}
|
||||
{/* Odkaz na zoznam / úpravu v Brevo */}
|
||||
<a
|
||||
href="https://app.brevo.com/campaigns"
|
||||
href={brevoCampaignUrl || brevoListingUrl || 'https://app.brevo.com/campaigns/listing'}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="flex items-center gap-1 text-xs font-bold text-white bg-emerald-600 hover:bg-emerald-700 px-3 py-1.2 rounded-lg transition-all shadow-xs"
|
||||
@@ -235,6 +235,17 @@ export const TopBar: React.FC<TopBarProps> = ({
|
||||
<span className="hidden xl:inline">{isExportingBrevo ? 'Ukladám...' : 'Aktualizovať'}</span>
|
||||
</button>
|
||||
|
||||
{/* Tlačidlo na odoslanie ako úplne novej kampane */}
|
||||
<button
|
||||
onClick={() => onExportBrevo(false)}
|
||||
disabled={isExportingBrevo}
|
||||
className="flex items-center gap-1 text-xs font-bold text-emerald-800 hover:bg-emerald-100 px-2 py-1.2 rounded-lg transition-all"
|
||||
title="Vytvoriť a odoslať túto kampaň do Brevo ako novú kópiu"
|
||||
>
|
||||
<Send className="w-3 h-3 text-emerald-700" />
|
||||
<span className="hidden 2xl:inline">Ako novú</span>
|
||||
</button>
|
||||
|
||||
{/* Tlačidlo na overenie stavu */}
|
||||
<button
|
||||
onClick={() => verifyCampaignInBrevo()}
|
||||
|
||||
+94
-71
@@ -273,7 +273,7 @@ function renderModule(m: any, campaign: NewsletterCampaign): string {
|
||||
<tr>
|
||||
<td>
|
||||
<a href="${escapeHtml(m.data.linkUrl || '#')}">
|
||||
<img src="${escapeHtml(m.data.imageUrl)}" width="600" alt="${escapeHtml(m.data.altText || '')}" style="display: block; border: 0; width: 100%; max-width: 100%; border-radius: ${m.data.title || m.data.description || m.data.buttonText ? '16px 16px 0 0' : '16px'};">
|
||||
<img src="${escapeHtml(m.data.imageUrl)}" width="600" alt="${escapeHtml(m.data.altText || m.data.title || m.title || 'COOP Jednota')}" style="display: block; border: 0; width: 100%; max-width: 100%; border-radius: ${m.data.title || m.data.description || m.data.buttonText ? '16px 16px 0 0' : '16px'};">
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -315,10 +315,10 @@ function renderModule(m: any, campaign: NewsletterCampaign): string {
|
||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%" style="margin-bottom: 12px;">
|
||||
<tr>
|
||||
${row.map((p, idx) => `
|
||||
<td width="50%" valign="top" height="1" style="padding-${idx === 0 ? 'right: 6px' : 'left: 6px'}; padding-bottom: 0;">
|
||||
${renderExactProductCard(p, globalValidity, cardBg, cardBorder, badgeHdrBg, badgeHdrColor, badgePrcBg, badgePrcColor, badgeCustomTxt)}
|
||||
<td width="50%" valign="top" height="100%" style="padding-${idx === 0 ? 'right: 6px' : 'left: 6px'}; padding-bottom: 0; height: 100%;">
|
||||
${renderExactProductCard(p, globalValidity, cardBg, cardBorder, badgeHdrBg, badgeHdrColor, badgePrcBg, badgePrcColor, badgeCustomTxt, m.data.sectionTitle)}
|
||||
</td>`).join('\n')}
|
||||
${row.length === 1 ? '<td width="50%" valign="top"></td>' : ''}
|
||||
${row.length === 1 ? '<td width="50%" valign="top" height="100%" style="height: 100%;"></td>' : ''}
|
||||
</tr>
|
||||
</table>
|
||||
`).join('\n');
|
||||
@@ -359,7 +359,7 @@ function renderModule(m: any, campaign: NewsletterCampaign): string {
|
||||
<tr>
|
||||
<td>
|
||||
<a href="${escapeHtml(m.data.headerLink || '#')}">
|
||||
<img src="${escapeHtml(m.data.headerImageUrl)}" width="600" alt="Vernostné zľavy" style="display: block; border: 0; width: 100%; max-width: 100%; border-radius: 16px;">
|
||||
<img src="${escapeHtml(m.data.headerImageUrl)}" width="600" alt="${escapeHtml(m.data.title || m.data.sectionTitle || 'Vernostné zľavy')}" style="display: block; border: 0; width: 100%; max-width: 100%; border-radius: 16px;">
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -372,7 +372,7 @@ function renderModule(m: any, campaign: NewsletterCampaign): string {
|
||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
|
||||
<tr>
|
||||
${lProducts.map((p: any, idx: number) => `
|
||||
<td width="50%" valign="top" height="1" style="padding-${idx === 0 ? 'right: 6px' : 'left: 6px'}; padding-bottom: 0;">
|
||||
<td width="50%" valign="top" height="100%" style="padding-${idx === 0 ? 'right: 6px' : 'left: 6px'}; padding-bottom: 0; height: 100%;">
|
||||
${renderExactLoyaltyCard(p, m.data.globalValidity || '2. 5. – 15. 5. 2026')}
|
||||
</td>`).join('\n')}
|
||||
</tr>
|
||||
@@ -393,22 +393,32 @@ function renderModule(m: any, campaign: NewsletterCampaign): string {
|
||||
<table align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
|
||||
<tr>
|
||||
<!-- Leták 1 -->
|
||||
<td width="50%" valign="top" style="padding-right: 6px;">
|
||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%" bgcolor="${it1.bgColor}" style="background-color: ${it1.bgColor}; border: 0; border-radius: 16px; overflow: hidden; box-shadow: 0 8px 25px rgba(0, 0, 0, 0.25);">
|
||||
<tr>
|
||||
<td>
|
||||
<td width="50%" valign="top" height="100%" style="padding-right: 6px; height: 100%;">
|
||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%" height="100%" bgcolor="${it1.bgColor}" style="background-color: ${it1.bgColor}; border: 0; border-radius: 16px; overflow: hidden; box-shadow: 0 8px 25px rgba(0, 0, 0, 0.25); height: 100%; min-height: 100%;">
|
||||
<tr height="1">
|
||||
<td valign="top" style="line-height: 0; height: 1px;">
|
||||
<a href="${escapeHtml(it1.linkUrl || '#')}">
|
||||
<img src="${escapeHtml(it1.imageUrl)}" width="300" alt="${escapeHtml(it1.title)}" style="display: block; border: 0; width: 100%; max-width: 100%;">
|
||||
<img src="${escapeHtml(it1.imageUrl)}" width="300" alt="${escapeHtml(it1.title || m.data.title || m.title || 'Aktuálny leták')}" style="display: block; border: 0; width: 100%; max-width: 100%;">
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 25px 15px 30px 15px; text-align: center;">
|
||||
<h3 class="force-text-white" style="margin: 0 0 15px 0; font-size: 17px; color: ${it1.textColor || '#fefefe'}; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px;">${escapeHtml(it1.title)}</h3>
|
||||
<table align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" style="margin: auto;" class="btn-table">
|
||||
<td valign="bottom" style="padding: 20px 15px 25px 15px; text-align: center; height: 100%;">
|
||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%" height="100%" style="height: 100%;">
|
||||
<tr>
|
||||
<td style="text-align: center;">
|
||||
<a href="${escapeHtml(it1.linkUrl || '#')}" class="btn force-text-white" style="background-color: ${it1.btnBgColor || '#e2001a'}; color: #fefefe; font-family: 'Poppins', sans-serif; font-size: 12px; font-weight: 800; text-decoration: none; padding: 10px 24px; border-radius: 25px; display: inline-block; text-transform: uppercase; letter-spacing: 0.5px; box-shadow: 0 4px 12px rgba(226, 0, 26, 0.35);">${escapeHtml(it1.btnText)}</a>
|
||||
<td valign="top" style="text-align: center; min-height: 44px; padding-bottom: 15px;">
|
||||
<h3 class="force-text-white" style="margin: 0; font-size: 17px; color: ${it1.textColor || '#fefefe'}; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px; line-height: 1.25;">${escapeHtml(it1.title)}</h3>
|
||||
</td>
|
||||
</tr>
|
||||
<tr height="1">
|
||||
<td valign="bottom" align="center" style="text-align: center; height: 1px;">
|
||||
<table align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" style="margin: auto;" class="btn-table">
|
||||
<tr>
|
||||
<td style="text-align: center;">
|
||||
<a href="${escapeHtml(it1.linkUrl || '#')}" class="btn force-text-white" style="background-color: ${it1.btnBgColor || '#e2001a'}; color: #fefefe; font-family: 'Poppins', sans-serif; font-size: 12px; font-weight: 800; text-decoration: none; padding: 10px 24px; border-radius: 25px; display: inline-block; text-transform: uppercase; letter-spacing: 0.5px; box-shadow: 0 4px 12px rgba(226, 0, 26, 0.35);">${escapeHtml(it1.btnText)}</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
@@ -417,22 +427,32 @@ function renderModule(m: any, campaign: NewsletterCampaign): string {
|
||||
</table>
|
||||
</td>
|
||||
<!-- Leták 2 -->
|
||||
<td width="50%" valign="top" style="padding-left: 6px;">
|
||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%" bgcolor="${it2.bgColor}" style="background-color: ${it2.bgColor}; border: 0; border-radius: 16px; overflow: hidden; box-shadow: 0 8px 25px rgba(0, 0, 0, 0.25);">
|
||||
<tr>
|
||||
<td>
|
||||
<td width="50%" valign="top" height="100%" style="padding-left: 6px; height: 100%;">
|
||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%" height="100%" bgcolor="${it2.bgColor}" style="background-color: ${it2.bgColor}; border: 0; border-radius: 16px; overflow: hidden; box-shadow: 0 8px 25px rgba(0, 0, 0, 0.25); height: 100%; min-height: 100%;">
|
||||
<tr height="1">
|
||||
<td valign="top" style="line-height: 0; height: 1px;">
|
||||
<a href="${escapeHtml(it2.linkUrl || '#')}">
|
||||
<img src="${escapeHtml(it2.imageUrl)}" width="300" alt="${escapeHtml(it2.title)}" style="display: block; border: 0; width: 100%; max-width: 100%;">
|
||||
<img src="${escapeHtml(it2.imageUrl)}" width="300" alt="${escapeHtml(it2.title || m.data.title || m.title || 'Aktuálny leták')}" style="display: block; border: 0; width: 100%; max-width: 100%;">
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 25px 15px 30px 15px; text-align: center;">
|
||||
<h3 style="margin: 0 0 15px 0; font-size: 17px; color: ${it2.textColor || '#29446f'}; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px;">${escapeHtml(it2.title)}</h3>
|
||||
<table align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" style="margin: auto;" class="btn-table">
|
||||
<td valign="bottom" style="padding: 20px 15px 25px 15px; text-align: center; height: 100%;">
|
||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%" height="100%" style="height: 100%;">
|
||||
<tr>
|
||||
<td style="text-align: center;">
|
||||
<a href="${escapeHtml(it2.linkUrl || '#')}" class="btn force-text-white" style="background-color: ${it2.btnBgColor || '#29446f'}; color: #fefefe; font-family: 'Poppins', sans-serif; font-size: 12px; font-weight: 800; text-decoration: none; padding: 10px 24px; border-radius: 25px; display: inline-block; text-transform: uppercase; letter-spacing: 0.5px; box-shadow: 0 4px 12px rgba(41, 68, 111, 0.3);">${escapeHtml(it2.btnText)}</a>
|
||||
<td valign="top" style="text-align: center; min-height: 44px; padding-bottom: 15px;">
|
||||
<h3 style="margin: 0; font-size: 17px; color: ${it2.textColor || '#29446f'}; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px; line-height: 1.25;">${escapeHtml(it2.title)}</h3>
|
||||
</td>
|
||||
</tr>
|
||||
<tr height="1">
|
||||
<td valign="bottom" align="center" style="text-align: center; height: 1px;">
|
||||
<table align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" style="margin: auto;" class="btn-table">
|
||||
<tr>
|
||||
<td style="text-align: center;">
|
||||
<a href="${escapeHtml(it2.linkUrl || '#')}" class="btn force-text-white" style="background-color: ${it2.btnBgColor || '#29446f'}; color: #fefefe; font-family: 'Poppins', sans-serif; font-size: 12px; font-weight: 800; text-decoration: none; padding: 10px 24px; border-radius: 25px; display: inline-block; text-transform: uppercase; letter-spacing: 0.5px; box-shadow: 0 4px 12px rgba(41, 68, 111, 0.3);">${escapeHtml(it2.btnText)}</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
@@ -451,10 +471,10 @@ function renderModule(m: any, campaign: NewsletterCampaign): string {
|
||||
<table align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
|
||||
<tr>
|
||||
<!-- Článok 1 -->
|
||||
<td width="50%" valign="top" style="padding-right: 6px; padding-bottom: 20px;">
|
||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%" bgcolor="${it1.bgColor}" style="background-color: ${it1.bgColor}; border: 0; border-radius: 16px; overflow: hidden; box-shadow: 0 4px 15px rgba(0,0,0,0.15);">
|
||||
<tr>
|
||||
<td background="${escapeHtml(it1.imageUrl)}" bgcolor="${it1.bgColor}" width="300" height="240" valign="bottom" style="background-image: url('${escapeHtml(it1.imageUrl)}'); background-size: cover; background-position: center;">
|
||||
<td width="50%" valign="top" height="100%" style="padding-right: 6px; padding-bottom: 20px; height: 100%;">
|
||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%" height="100%" bgcolor="${it1.bgColor}" style="background-color: ${it1.bgColor}; border: 0; border-radius: 16px; overflow: hidden; box-shadow: 0 4px 15px rgba(0,0,0,0.15); height: 100%; min-height: 100%;">
|
||||
<tr height="240">
|
||||
<td background="${escapeHtml(it1.imageUrl)}" bgcolor="${it1.bgColor}" width="300" height="240" valign="bottom" style="background-image: url('${escapeHtml(it1.imageUrl)}'); background-size: cover; background-position: center; height: 240px;">
|
||||
<!--[if gte mso 9]>
|
||||
<v:rect xmlns:v="urn:schemas-microsoft-com:vml" fill="true" stroke="false" style="width:300px;height:240px;">
|
||||
<v:fill type="frame" src="${escapeHtml(it1.imageUrl)}" color="${it1.bgColor}" />
|
||||
@@ -464,7 +484,7 @@ function renderModule(m: any, campaign: NewsletterCampaign): string {
|
||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%" height="100%">
|
||||
<tr>
|
||||
<td align="center" valign="bottom" style="padding-bottom: 10px;">
|
||||
<img src="${escapeHtml(it1.badgeImgUrl)}" width="70" alt="Recepty" style="display: block; border: 0; margin: 0 auto;">
|
||||
<img src="${escapeHtml(it1.badgeImgUrl)}" width="70" alt="${escapeHtml(it1.title || 'Recepty')}" style="display: block; border: 0; margin: 0 auto;">
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
@@ -473,17 +493,17 @@ function renderModule(m: any, campaign: NewsletterCampaign): string {
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 10px 15px 25px 15px; text-align: center; height: 60px;" valign="top">
|
||||
<h3 class="force-text-white" style="margin: 0; font-size: 17px; color: #fefefe; font-weight: 800; text-transform: uppercase; letter-spacing: 0.8px; line-height: 1.2;">${it1.title}</h3>
|
||||
<td style="padding: 15px 15px 25px 15px; text-align: center; height: 100%;" valign="middle">
|
||||
<h3 class="force-text-white" style="margin: 0; font-size: 17px; color: #fefefe; font-weight: 800; text-transform: uppercase; letter-spacing: 0.8px; line-height: 1.25;">${escapeHtml(it1.title)}</h3>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<!-- Článok 2 -->
|
||||
<td width="50%" valign="top" style="padding-left: 6px; padding-bottom: 20px;">
|
||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%" bgcolor="${it2.bgColor}" style="background-color: ${it2.bgColor}; border: 0; border-radius: 16px; overflow: hidden; box-shadow: 0 4px 15px rgba(0,0,0,0.15);">
|
||||
<tr>
|
||||
<td background="${escapeHtml(it2.imageUrl)}" bgcolor="${it2.bgColor}" width="300" height="240" valign="bottom" style="background-image: url('${escapeHtml(it2.imageUrl)}'); background-size: cover; background-position: center;">
|
||||
<td width="50%" valign="top" height="100%" style="padding-left: 6px; padding-bottom: 20px; height: 100%;">
|
||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%" height="100%" bgcolor="${it2.bgColor}" style="background-color: ${it2.bgColor}; border: 0; border-radius: 16px; overflow: hidden; box-shadow: 0 4px 15px rgba(0,0,0,0.15); height: 100%; min-height: 100%;">
|
||||
<tr height="240">
|
||||
<td background="${escapeHtml(it2.imageUrl)}" bgcolor="${it2.bgColor}" width="300" height="240" valign="bottom" style="background-image: url('${escapeHtml(it2.imageUrl)}'); background-size: cover; background-position: center; height: 240px;">
|
||||
<!--[if gte mso 9]>
|
||||
<v:rect xmlns:v="urn:schemas-microsoft-com:vml" fill="true" stroke="false" style="width:300px;height:240px;">
|
||||
<v:fill type="frame" src="${escapeHtml(it2.imageUrl)}" color="${it2.bgColor}" />
|
||||
@@ -493,7 +513,7 @@ function renderModule(m: any, campaign: NewsletterCampaign): string {
|
||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%" height="100%">
|
||||
<tr>
|
||||
<td align="center" valign="bottom" style="padding-bottom: 10px;">
|
||||
<img src="${escapeHtml(it2.badgeImgUrl)}" width="70" alt="Časopis Jednota" style="display: block; border: 0; margin: 0 auto;">
|
||||
<img src="${escapeHtml(it2.badgeImgUrl)}" width="70" alt="${escapeHtml(it2.title || 'Časopis Jednota')}" style="display: block; border: 0; margin: 0 auto;">
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
@@ -502,8 +522,8 @@ function renderModule(m: any, campaign: NewsletterCampaign): string {
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 10px 15px 25px 15px; text-align: center; height: 60px;" valign="top">
|
||||
<h3 class="force-text-white" style="margin: 0; font-size: 17px; color: #fefefe; font-weight: 800; text-transform: uppercase; letter-spacing: 0.8px; line-height: 1.2;">${it2.title}</h3>
|
||||
<td style="padding: 15px 15px 25px 15px; text-align: center; height: 100%;" valign="middle">
|
||||
<h3 class="force-text-white" style="margin: 0; font-size: 17px; color: #fefefe; font-weight: 800; text-transform: uppercase; letter-spacing: 0.8px; line-height: 1.25;">${escapeHtml(it2.title)}</h3>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
@@ -586,21 +606,23 @@ function renderExactProductCard(
|
||||
badgeHdrColor: string,
|
||||
badgePrcBg: string,
|
||||
badgePrcColor: string,
|
||||
badgeCustomTxt: string | null
|
||||
badgeCustomTxt: string | null,
|
||||
sectionTitle?: string
|
||||
): string {
|
||||
const validity = p.validityOverride || globalValidity;
|
||||
const effectiveCardBg = p.cardBgColor || cardBg || '#feeaea';
|
||||
|
||||
const storesHtml = `
|
||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" align="right">
|
||||
${p.stores?.potraviny ? `<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: #e2001a; padding: 0; line-height: 0;"><img src="${SUPABASE_ASSETS_BASE}stit_potraviny.png" height="10" alt="P" style="display: block; height: 10px; width: auto; border: 0;"></td></tr></table></td></tr>` : ''}
|
||||
${p.stores?.supermarket ? `<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: #f9890e; padding: 0; line-height: 0;"><img src="${SUPABASE_ASSETS_BASE}stit_supermarket.png" height="10" alt="S" style="display: block; height: 10px; width: auto; border: 0;"></td></tr></table></td></tr>` : ''}
|
||||
${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="T" style="display: block; height: 10px; width: auto; border: 0;"></td></tr></table></td></tr>` : ''}
|
||||
${p.stores?.potraviny ? `<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: #e2001a; padding: 0; line-height: 0;"><img src="${SUPABASE_ASSETS_BASE}stit_potraviny.png" height="10" alt="Potraviny" style="display: block; height: 10px; width: auto; border: 0;"></td></tr></table></td></tr>` : ''}
|
||||
${p.stores?.supermarket ? `<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: #f9890e; padding: 0; line-height: 0;"><img src="${SUPABASE_ASSETS_BASE}stit_supermarket.png" height="10" alt="Supermarket" style="display: block; height: 10px; width: auto; border: 0;"></td></tr></table></td></tr>` : ''}
|
||||
${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>`;
|
||||
|
||||
return `
|
||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%" height="100%" class="glass-product" bgcolor="${cardBg}" style="background-color: ${cardBg}; border: 0; border-radius: 16px; box-shadow: 0 4px 15px rgba(0, 0, 0, 0.15);">
|
||||
<tr>
|
||||
<td style="padding: 15px 15px 0 15px;" valign="top">
|
||||
<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 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>
|
||||
@@ -609,14 +631,14 @@ function renderExactProductCard(
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr height="1">
|
||||
<td style="padding: 0 8px 15px 8px; text-align: center; height: 160px;" valign="middle">
|
||||
<img src="${escapeHtml(p.imageUrl)}" width="220" alt="${escapeHtml(p.title)}" style="display: block; width: 100%; max-width: 220px; margin: 0 auto; border-radius: 8px;">
|
||||
<img src="${escapeHtml(p.imageUrl)}" width="220" alt="${escapeHtml(p.title || sectionTitle || 'Produkt')}" style="display: block; width: 100%; max-width: 220px; margin: 0 auto; border-radius: 8px;">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 0 8px 10px 8px; text-align: center; height: 50px;" valign="top">
|
||||
<h3 class="force-text-dark" style="margin: 0; font-size: 15px; color: #1a1a1a; font-weight: 600;">${escapeHtml(p.title)}</h3>
|
||||
<td style="padding: 0 8px 10px 8px; text-align: center; height: 100%; min-height: 44px;" 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>
|
||||
<tr height="1">
|
||||
@@ -646,7 +668,7 @@ function renderExactProductCard(
|
||||
${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);">
|
||||
<img src="${SUPABASE_ASSETS_BASE}vlajka_srdce.png" width="40" alt="Slovenský výrobok" 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>`;
|
||||
@@ -658,7 +680,7 @@ function renderExactProductCard(
|
||||
<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;">
|
||||
<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>`;
|
||||
@@ -696,15 +718,15 @@ function renderExactProductCard(
|
||||
${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);">
|
||||
<img src="${SUPABASE_ASSETS_BASE}vlajka_srdce.png" width="40" alt="Slovenský výrobok" 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>`;
|
||||
})()}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" style="padding: 2px 8px 12px 8px; text-align: center;">
|
||||
<tr height="1">
|
||||
<td align="center" valign="bottom" style="padding: 2px 8px 12px 8px; text-align: center; height: 1px;">
|
||||
${p.unitPrice ? `<div style="font-size: 9px; color: #666666; font-weight: 500; font-family: Arial, sans-serif; text-align: center;">${escapeHtml(p.unitPrice)}</div>` : '<div style="font-size: 9px; line-height: 9px; height: 9px;"> </div>'}
|
||||
</td>
|
||||
</tr>
|
||||
@@ -715,15 +737,16 @@ function renderExactLoyaltyCard(p: any, validity: string): string {
|
||||
const cardValidity = p.validityOverride || validity;
|
||||
const storesHtml = `
|
||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" align="right">
|
||||
${p.stores?.potraviny ? `<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: #e2001a; padding: 0; line-height: 0;"><img src="${SUPABASE_ASSETS_BASE}stit_potraviny.png" height="10" alt="P" style="display: block; height: 10px; width: auto; border: 0;"></td></tr></table></td></tr>` : ''}
|
||||
${p.stores?.supermarket ? `<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: #f9890e; padding: 0; line-height: 0;"><img src="${SUPABASE_ASSETS_BASE}stit_supermarket.png" height="10" alt="S" style="display: block; height: 10px; width: auto; border: 0;"></td></tr></table></td></tr>` : ''}
|
||||
${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="T" style="display: block; height: 10px; width: auto; border: 0;"></td></tr></table></td></tr>` : ''}
|
||||
${p.stores?.potraviny ? `<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: #e2001a; padding: 0; line-height: 0;"><img src="${SUPABASE_ASSETS_BASE}stit_potraviny.png" height="10" alt="Potraviny" style="display: block; height: 10px; width: auto; border: 0;"></td></tr></table></td></tr>` : ''}
|
||||
${p.stores?.supermarket ? `<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: #f9890e; padding: 0; line-height: 0;"><img src="${SUPABASE_ASSETS_BASE}stit_supermarket.png" height="10" alt="Supermarket" style="display: block; height: 10px; width: auto; border: 0;"></td></tr></table></td></tr>` : ''}
|
||||
${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 loyaltyBg = p.cardBgColor || '#e6e1d9';
|
||||
return `
|
||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%" height="100%" class="glass-product card-vernostna" bgcolor="#e6e1d9" style="background-color: #e6e1d9; border: 0; border-radius: 16px; box-shadow: 0 4px 15px rgba(0, 0, 0, 0.15);">
|
||||
<tr>
|
||||
<td style="padding: 15px 15px 0 15px;" valign="top">
|
||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%" height="100%" class="glass-product card-vernostna" bgcolor="${loyaltyBg}" style="background-color: ${loyaltyBg}; 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 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(cardValidity)}</td>
|
||||
@@ -732,18 +755,18 @@ function renderExactLoyaltyCard(p: any, validity: string): string {
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr height="1">
|
||||
<td style="padding: 0 8px 15px 8px; text-align: center; height: 160px;" valign="middle">
|
||||
<img src="${escapeHtml(p.imageUrl)}" width="220" alt="${escapeHtml(p.title)}" style="display: block; width: 100%; max-width: 220px; margin: 0 auto; border-radius: 8px;">
|
||||
<img src="${escapeHtml(p.imageUrl)}" width="220" alt="${escapeHtml(p.title || 'Produkt')}" style="display: block; width: 100%; max-width: 220px; margin: 0 auto; border-radius: 8px;">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 0 8px 10px 8px; text-align: center; height: 50px;" valign="top">
|
||||
<h3 class="force-text-dark" style="margin: 0; font-size: 15px; color: #1a1a1a; font-weight: 600;">${escapeHtml(p.title)}</h3>
|
||||
<td style="padding: 0 8px 10px 8px; text-align: center; height: 100%; min-height: 44px;" 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>
|
||||
<tr height="1">
|
||||
<td style="padding: 0 8px ${p.badgeCustomTemplate ? '4px' : '12px'} 8px; text-align: center;" valign="bottom">
|
||||
<td style="padding: 0 8px ${p.badgeCustomTemplate ? '4px' : '12px'} 8px; text-align: center; height: 1px;" valign="bottom">
|
||||
${(() => {
|
||||
// 1. Ak má vernostný produkt vlastnú dynamickú šablónu cenovky
|
||||
if (p.badgeCustomTemplate) {
|
||||
@@ -776,7 +799,7 @@ function renderExactLoyaltyCard(p: any, validity: string): string {
|
||||
${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);">
|
||||
<img src="${SUPABASE_ASSETS_BASE}vlajka_srdce.png" width="40" alt="Slovenský výrobok" 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>`;
|
||||
@@ -831,7 +854,7 @@ function renderExactLoyaltyCard(p: any, validity: string): string {
|
||||
${p.showSlovakFlag ? `
|
||||
<tr>
|
||||
<td colspan="2" 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);">
|
||||
<img src="${SUPABASE_ASSETS_BASE}vlajka_srdce.png" width="40" alt="Slovenský výrobok" 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>` : ''}
|
||||
<tr>
|
||||
@@ -847,8 +870,8 @@ function renderExactLoyaltyCard(p: any, validity: string): string {
|
||||
</td>
|
||||
</tr>
|
||||
${p.badgeCustomTemplate ? `
|
||||
<tr>
|
||||
<td align="center" style="padding: 2px 8px 12px 8px; text-align: center;">
|
||||
<tr height="1">
|
||||
<td align="center" valign="bottom" style="padding: 2px 8px 12px 8px; text-align: center; height: 1px;">
|
||||
${p.cardUnitPrice || p.unitPrice ? `<div style="font-size: 9px; color: #666666; font-weight: 500; font-family: Arial, sans-serif; text-align: center;">${escapeHtml(p.cardUnitPrice || p.unitPrice)}</div>` : '<div style="font-size: 9px; line-height: 9px; height: 9px;"> </div>'}
|
||||
</td>
|
||||
</tr>` : ''}
|
||||
|
||||
@@ -90,6 +90,8 @@ export interface ProductsGridModuleData {
|
||||
sectionTitle: string;
|
||||
globalValidity: string;
|
||||
products: ProductItem[];
|
||||
cardBgColor?: string;
|
||||
cardBorderColor?: string;
|
||||
}
|
||||
|
||||
export interface LoyaltyClubModuleData {
|
||||
|
||||
Reference in new issue
Block a user