diff --git a/src/app/page.tsx b/src/app/page.tsx index 1a5ef81..4b99026 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -572,7 +572,8 @@ export default function Home() { ...m, data: { ...m.data, - products: (m.data.products || []).map((prod: any) => ({ + // Produkty s vlastnou PNG cenovkou (výnimky) sa neprepisujú + products: (m.data.products || []).map((prod: any) => prod.customBadgePngUrl ? prod : ({ ...prod, badgeId: badge.id, badgeCustomTemplate: badge, @@ -580,8 +581,7 @@ export default function Home() { badgeAlign: badge.align ?? prod.badgeAlign ?? 'center', badgePaddingTop: badge.paddingTop ?? prod.badgePaddingTop ?? 4, badgePaddingBottom: badge.paddingBottom ?? prod.badgePaddingBottom ?? 4, - badgeLayout: badgeLayout ?? prod.badgeLayout, - customBadgePngUrl: undefined + badgeLayout: badgeLayout ?? prod.badgeLayout })) } }; diff --git a/src/components/editor/ConfigPanel.tsx b/src/components/editor/ConfigPanel.tsx index fcc431b..8ad8b27 100644 --- a/src/components/editor/ConfigPanel.tsx +++ b/src/components/editor/ConfigPanel.tsx @@ -26,6 +26,29 @@ interface ConfigPanelProps { availableBadges?: BadgeTemplate[]; } +// Nahratie celej cenovky ako PNG pre výnimočný produkt (prekryje šablónu) +const CustomBadgePngInput: React.FC<{ value?: string; onChange: (url: string) => void }> = ({ value, onChange }) => ( +
+ + {value ? ( + + ) : ( +

Nahraná PNG nahradí generovanú cenovku len pri tomto produkte.

+ )} +
+); + export const ConfigPanel: React.FC = ({ module, onUpdateModule, @@ -731,6 +754,16 @@ export const ConfigPanel: React.FC = ({ + {/* Vlastná PNG cenovka (výnimka): prekryje šablónu, po odstránení sa vráti generovaná */} + { + const products = [...module.data.products]; + products[pIdx].customBadgePngUrl = url || undefined; + updateData({ products }); + }} + /> + {/* Tlačidlá aplikácie cenovky */} {p.badgeCustomTemplate && (
@@ -738,7 +771,8 @@ export const ConfigPanel: React.FC = ({ type="button" onClick={() => { if (confirm(`Naozaj chcete aplikovať šablónu "${p.badgeCustomTemplate?.name}" na všetky produkty v tejto sekcii?`)) { - const products = (module.data.products || []).map((prod: ProductItem) => ({ + // Produkty s vlastnou PNG cenovkou (výnimky) sa neprepisujú + const products = (module.data.products || []).map((prod: ProductItem) => prod.customBadgePngUrl ? prod : ({ ...prod, badgeCustomTemplate: p.badgeCustomTemplate, badgeId: p.badgeCustomTemplate?.id, @@ -746,8 +780,7 @@ export const ConfigPanel: React.FC = ({ badgeAlign: p.badgeAlign || p.badgeCustomTemplate?.align || 'center', badgePaddingTop: p.badgePaddingTop ?? p.badgeCustomTemplate?.paddingTop ?? 4, badgePaddingBottom: p.badgePaddingBottom ?? p.badgeCustomTemplate?.paddingBottom ?? 4, - badgeLayout: p.badgeLayout || 'below', - customBadgePngUrl: undefined + badgeLayout: p.badgeLayout || 'below' })); updateData({ products }); } @@ -1347,6 +1380,7 @@ export const ConfigPanel: React.FC = ({ if (val === 'default_loyalty') { products[pIdx].badgeCustomTemplate = undefined; products[pIdx].badgeId = undefined; + products[pIdx].customBadgePngUrl = undefined; } else { const found = (availableBadges || []).find((b) => b.id === val); if (found) { @@ -1356,6 +1390,7 @@ export const ConfigPanel: React.FC = ({ products[pIdx].badgeAlign = found.align ?? products[pIdx].badgeAlign ?? 'center'; products[pIdx].badgePaddingTop = found.paddingTop ?? products[pIdx].badgePaddingTop ?? 4; products[pIdx].badgePaddingBottom = found.paddingBottom ?? products[pIdx].badgePaddingBottom ?? 4; + products[pIdx].customBadgePngUrl = undefined; } } updateData({ products }); @@ -1371,6 +1406,16 @@ export const ConfigPanel: React.FC = ({
+ {/* Vlastná PNG cenovka (výnimka): prekryje šablónu, po odstránení sa vráti generovaná */} + { + const products = [...module.data.products]; + products[pIdx].customBadgePngUrl = url || undefined; + updateData({ products }); + }} + /> + {/* Tlačidlá aplikácie cenovky */} {p.badgeCustomTemplate && (
@@ -1378,7 +1423,8 @@ export const ConfigPanel: React.FC = ({ type="button" onClick={() => { if (confirm(`Naozaj chcete aplikovať šablónu "${p.badgeCustomTemplate?.name}" na všetky vernostné produkty?`)) { - const products = (module.data.products || []).map((prod: any) => ({ + // Produkty s vlastnou PNG cenovkou (výnimky) sa neprepisujú + const products = (module.data.products || []).map((prod: any) => prod.customBadgePngUrl ? prod : ({ ...prod, badgeCustomTemplate: p.badgeCustomTemplate, badgeId: p.badgeCustomTemplate?.id, @@ -1458,7 +1504,7 @@ export const ConfigPanel: React.FC = ({ )} {/* Rýchle ovládanie veľkosti (Width), zarovnania a paddingu pre vernostnú cenovku */} - {p.badgeCustomTemplate && ( + {(p.badgeCustomTemplate || p.customBadgePngUrl) && (
{/* Šírka */}
diff --git a/src/lib/emailRenderer.ts b/src/lib/emailRenderer.ts index b085426..98ed80d 100644 --- a/src/lib/emailRenderer.ts +++ b/src/lib/emailRenderer.ts @@ -642,16 +642,7 @@ function renderExactProductCard( // Pomocná funkcia na render samotnej cenovky (bez obalového ) const renderBadgeContent = (bWidth: number, bAlign: string, padTop: number, padBottom: number, marginStyle: string) => { - if (p.badgeCustomTemplate) { - return ` - - - - -
- ${renderCleanBadgeSvg(p.badgeCustomTemplate, p, bWidth)} -
`; - } + // Vlastná PNG cenovka (výnimka) má prednosť pred šablónou; po jej odstránení sa vráti šablóna if (p.customBadgePngUrl) { return ` @@ -662,6 +653,16 @@ function renderExactProductCard(
`; } + 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 ` @@ -809,14 +810,14 @@ function renderExactLoyaltyCard(p: any, validity: string): string { - + ${(() => { - // 1. Ak má vernostný produkt vlastnú dynamickú šablónu cenovky - if (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); + // 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') { @@ -836,7 +837,9 @@ function renderExactLoyaltyCard(p: any, validity: string): string {
- ${renderCleanBadgeSvg(p.badgeCustomTemplate, loyaltyProductData, bWidth)} + ${p.customBadgePngUrl + ? `${escapeHtml(pickAlt(p.title, 'Cenovka'))}` + : renderCleanBadgeSvg(p.badgeCustomTemplate, loyaltyProductData, bWidth)}
`; @@ -900,7 +903,7 @@ function renderExactLoyaltyCard(p: any, validity: string): string { })()} - ${p.badgeCustomTemplate ? ` + ${p.badgeCustomTemplate || p.customBadgePngUrl ? ` ${p.cardUnitPrice || p.unitPrice ? `
${escapeHtml(p.cardUnitPrice || p.unitPrice)}
` : '
 
'}