feat: novy editor cenoviek - skutocna cenovka na platne, pohodlnejsia praca

- platno ukazuje skutocne SVG cenovky (rovnake ako v e-maile); vrstvy sa
  vyberaju a tahaju priamo na nej v suradniciach cenovky, s prichytenim na stred
- klavesnica: sipky posun (Shift = viac), Delete, Ctrl+Z / Ctrl+Y, Ctrl+S
- historia krokov (spat / znova), indikator neulozenych zmien, potvrdenie
  pri zatvoreni alebo prepnuti sablony
- prehladny panel: pozadie a predvolena sirka, vrstvy s rychlym pridanim,
  vybrana vrstva (text s klikatelnymi premennymi, pismo vratane Google/Adobe,
  rez, velkost, COOP farby, zarovnanie, X/Y, centy)
- skusobna cena na overenie dlhsich cien; Ulozit a pouzit na produkt
- odstranene nastavenia zarovnania a odsadenia (pri karte v style letaku
  nemaju vplyv)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Jakub_HostacnyandClaude Opus 5.5 committed 2026-10-21 11:57:35 +02:00
1 parent 419ad580ca
commit 5add629bb5
2 files changed
+779 -1254

No files matched your search

File diff suppressed because it is too large. Load diff
+3 -2
View File
@@ -90,7 +90,7 @@ export function renderCleanBadgeSvg(
const displayHeight = Math.round((displayWidth / vbWidth) * vbHeight); const displayHeight = Math.round((displayWidth / vbWidth) * vbHeight);
// Zostavenie textových vrstiev // Zostavenie textových vrstiev
const textLayersSvg = (template.layersConfig || []).map((layer) => { const textLayersSvg = (template.layersConfig || []).map((layer, layerIndex) => {
const rawText = layer.text || ''; const rawText = layer.text || '';
const fontSize = layer.fontSize || 16; const fontSize = layer.fontSize || 16;
const subFontSize = layer.indexFontSize || Math.max(10, Math.round(fontSize * 0.55)); const subFontSize = layer.indexFontSize || Math.max(10, Math.round(fontSize * 0.55));
@@ -125,7 +125,8 @@ export function renderCleanBadgeSvg(
contentSvg = escapeXml(replaceBadgeTextVars(rawText, product)); contentSvg = escapeXml(replaceBadgeTextVars(rawText, product));
} }
return `<text x="${layer.x}" y="${layer.y}" text-anchor="${anchor}" dominant-baseline="central" font-family="${fontFamily}" font-size="${fontSize}px" font-weight="${fontWeight}" fill="${fill}">${contentSvg}</text>`; // data-layer-index: editor cenoviek podľa neho nájde a odmeria vrstvu na plátne
return `<text data-layer-index="${layerIndex}" x="${layer.x}" y="${layer.y}" text-anchor="${anchor}" dominant-baseline="central" font-family="${fontFamily}" font-size="${fontSize}px" font-weight="${fontWeight}" fill="${fill}">${contentSvg}</text>`;
}).join('\n '); }).join('\n ');
return `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="${vb}" width="${displayWidth}" height="${displayHeight}" style="display:block;max-width:100%;height:auto;"> return `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="${vb}" width="${displayWidth}" height="${displayHeight}" style="display:block;max-width:100%;height:auto;">