feat: posun stitkov predajni pri kazdom produkte zvlast

Posuvniky Vodorovne / Zvisle su v nastaveniach cenovky produktu
(aj vernostneho) namiesto celej sekcie.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Jakub_HostacnyandClaude Opus 5.5 committed 2026-10-19 16:52:34 +02:00
1 parent a2d009bcb8
commit 139e3569d0
3 files changed
+42 -21

No files matched your search

+24 -16
View File
@@ -29,7 +29,7 @@ interface ConfigPanelProps {
availableBadges?: BadgeTemplate[];
}
// Posun štítkov predajní voči hornej hrane cenovky (pre celú sekciu)
// Posun štítkov predajní voči hornej hrane cenovky (pre jeden produkt)
const StoresOffsetControl: React.FC<{
x: number;
y: number;
@@ -67,7 +67,7 @@ const StoresOffsetControl: React.FC<{
</div>
{row('Vodorovne', x, -80, 80, 'storesOffsetX', '+ doprava, − doľava')}
{row('Zvisle', y, -40, 40, 'storesOffsetY', '+ vyššie nad cenovku, − nižšie cez horný okraj cenovky')}
<p className="text-[10px] text-gray-500">Štítky sú pri hornej hrane cenovky a posúvajú sa spolu s ňou. Platí pre celú sekciu.</p>
<p className="text-[10px] text-gray-500">Štítky sú pri hornej hrane cenovky a posúvajú sa spolu s ňou.</p>
</div>
);
};
@@ -613,13 +613,6 @@ export const ConfigPanel: React.FC<ConfigPanelProps> = ({
</label>
</div>
{/* Štítky predajní (Potraviny / Supermarket / Tempo) nad hornou hranou cenovky */}
<StoresOffsetControl
x={module.data.storesOffsetX || 0}
y={module.data.storesOffsetY ?? DEFAULT_STORES_OFFSET_Y}
onChange={(patch) => updateData(patch)}
/>
{/* Rozloženie produktov (Počet produktov na riadok) */}
<div>
<label className="block text-xs font-semibold text-gray-700 mb-1">
@@ -1093,6 +1086,17 @@ export const ConfigPanel: React.FC<ConfigPanelProps> = ({
}}
/>
{/* Štítky predajní (Potraviny / Supermarket / Tempo) pri hornej hrane cenovky */}
<StoresOffsetControl
x={p.storesOffsetX ?? module.data.storesOffsetX ?? 0}
y={p.storesOffsetY ?? module.data.storesOffsetY ?? DEFAULT_STORES_OFFSET_Y}
onChange={(patch) => {
const products = [...module.data.products];
products[pIdx] = { ...products[pIdx], ...patch };
updateData({ products });
}}
/>
{/* Tlačidlá aplikácie cenovky */}
{p.badgeCustomTemplate && (
<div className="space-y-1.5">
@@ -1366,13 +1370,6 @@ export const ConfigPanel: React.FC<ConfigPanelProps> = ({
</label>
</div>
{/* Štítky predajní (Potraviny / Supermarket / Tempo) nad hornou hranou cenovky */}
<StoresOffsetControl
x={module.data.storesOffsetX || 0}
y={module.data.storesOffsetY ?? DEFAULT_STORES_OFFSET_Y}
onChange={(patch) => updateData(patch)}
/>
{/* 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">
@@ -1798,6 +1795,17 @@ export const ConfigPanel: React.FC<ConfigPanelProps> = ({
}}
/>
{/* Štítky predajní (Potraviny / Supermarket / Tempo) pri hornej hrane cenovky */}
<StoresOffsetControl
x={p.storesOffsetX ?? module.data.storesOffsetX ?? 0}
y={p.storesOffsetY ?? module.data.storesOffsetY ?? DEFAULT_STORES_OFFSET_Y}
onChange={(patch) => {
const products = [...module.data.products];
products[pIdx] = { ...products[pIdx], ...patch };
updateData({ products });
}}
/>
{/* Tlačidlá aplikácie cenovky */}
{p.badgeCustomTemplate && (
<div className="space-y-1.5">
+13 -3
View File
@@ -792,12 +792,17 @@ function renderExactProductCard(
const effectiveCardBg = p.cardBgColor || cardBg || '#feeaea';
const storesHtml = renderStoresHtml(p);
// Posun štítkov je nastavenie produktu (staršie kampane mohli mať hodnotu na sekcii)
const productStoresOffset: StoresOffset = {
x: p.storesOffsetX ?? storesOffset.x,
y: p.storesOffsetY ?? storesOffset.y
};
const badgeLayout = p.badgeLayout || 'below';
// Cenovka so štítkami predajní nad hornou hranou (bez obalového <td>)
const renderBadgeContent = (bWidth: number, bAlign: string, padTop: number, padBottom: number, marginStyle: string) =>
attachStoresToBadge(renderBadgeOnly(bWidth, bAlign, 0, padBottom, marginStyle), storesHtml, bWidth, bAlign, marginStyle, padTop, storesOffset);
attachStoresToBadge(renderBadgeOnly(bWidth, bAlign, 0, padBottom, marginStyle), storesHtml, bWidth, bAlign, marginStyle, padTop, productStoresOffset);
// Pomocná funkcia na render samotnej cenovky (bez obalového <td>)
const renderBadgeOnly = (bWidth: number, bAlign: string, padTop: number, padBottom: number, marginStyle: string) => {
@@ -958,6 +963,11 @@ function renderExactProductCard(
function renderExactLoyaltyCard(p: any, validity: string, storesOffset: StoresOffset = {}): string {
const cardValidity = p.validityOverride || validity;
const storesHtml = renderStoresHtml(p);
// Posun štítkov je nastavenie produktu (staršie kampane mohli mať hodnotu na sekcii)
const productStoresOffset: StoresOffset = {
x: p.storesOffsetX ?? storesOffset.x,
y: p.storesOffsetY ?? storesOffset.y
};
const loyaltyBg = p.cardBgColor || '#e6e1d9';
return `
@@ -1027,7 +1037,7 @@ function renderExactLoyaltyCard(p: any, validity: string, storesOffset: StoresOf
: renderCleanBadgeSvg(p.badgeCustomTemplate, loyaltyProductData, bWidth)}
</td>
</tr>
</table>`, storesHtml, bWidth, bAlign, marginStyle, padTop, storesOffset);
</table>`, storesHtml, bWidth, bAlign, marginStyle, padTop, productStoresOffset);
}
// 2. Predvolený Dual Sticker Block (Bez karty / S kartou) 1:1
@@ -1084,7 +1094,7 @@ function renderExactLoyaltyCard(p: any, validity: string, storesOffset: StoresOf
<div style="font-size: 9px; color: #e2001a; font-weight: 800; font-family: Arial, sans-serif;">${escapeHtml(p.cardUnitPrice)}</div>
</td>
</tr>
</table>`, storesHtml, 140, 'center', 'margin: 0 auto;', 0, storesOffset);
</table>`, storesHtml, 140, 'center', 'margin: 0 auto;', 0, productStoresOffset);
})()}
</td>
</tr>
+5 -2
View File
@@ -47,6 +47,8 @@ export interface ProductItem {
showSlovakFlag?: boolean;
customBadgePngUrl?: string; // Voliteľná statická PNG cenovka
imageAlt?: string; // Ručný alt text fotky (inak názov produktu)
storesOffsetX?: number; // posun štítkov predajní voči cenovke (+ doprava)
storesOffsetY?: number; // posun štítkov predajní voči hornej hrane cenovky (+ vyššie)
imageScale?: number; // Zoom fotky (1 = 100 %)
imageOffsetX?: number; // Posun fotky vodorovne v px (+ doprava)
imageOffsetY?: number; // Posun fotky zvisle v px (+ nadol)
@@ -114,8 +116,9 @@ export interface ProductsGridModuleData {
cardBorderColor?: string;
columns?: 1 | 2;
showCardValidity?: boolean; // platnosť na kartách produktov (predvolene skrytá)
storesOffsetX?: number; // posun štítkov predajní voči cenovke (+ doprava)
storesOffsetY?: number; // posun štítkov predajní voči hornej hrane cenovky (+ vyššie)
// staršie kampane: posun štítkov na úrovni sekcie (dnes sa nastavuje pri produkte)
storesOffsetX?: number;
storesOffsetY?: number;
}
export interface LoyaltyClubModuleData {