feat: vernostne zlavy - pri neparnom pocte je prvy produkt cez cely riadok

Parny pocet: vsetky produkty po 2 v riadku. Neparny: prvy produkt sam cez
celu sirku (vacsi vizual), ostatne po 2. Export obrazkov kariet pouziva
rovnaku sirku karty ako nahlad.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Jakub_HostacnyandClaude Opus 5.5 committed 2026-10-21 13:03:35 +02:00
1 parent b13a447c64
commit 23f23c8903
3 files changed
+38 -15

No files matched your search

+33 -10
View File
@@ -372,23 +372,46 @@ export function renderProductCard(p: CardProduct, ctx: CardContext): string {
</table>`;
}
// Mriežka kariet (1 alebo 2 na riadok) s rovnakou výškou kariet v riadku
export function renderProductGrid(products: CardProduct[], ctx: CardContext): string {
const cols = ctx.cardWidth > 300 ? 1 : 2;
const rows: CardProduct[][] = [];
for (let i = 0; i < products.length; i += cols) rows.push(products.slice(i, i + cols));
return rows
// Kontext konkrétnej karty: vo vernostných zľavách pri nepárnom počte je prvý produkt cez celý riadok
export function cardContextFor(m: NewsletterModule, index: number, mode: RenderMode): CardContext {
const base = cardContextForModule(m, mode);
const count = (m.data.products || []).length;
if (base.variant === 'loyalty' && count % 2 === 1 && index === 0) return { ...base, cardWidth: 600 };
return base;
}
// Riadky mriežky (indexy produktov): 1 na riadok, alebo po 2;
// vernostné zľavy s nepárnym počtom: prvý produkt sám cez celý riadok, ostatné po 2
function gridRows(m: NewsletterModule, count: number, oneColumn: boolean): number[][] {
const idx = Array.from({ length: count }, (_, i) => i);
if (oneColumn) return idx.map((i) => [i]);
const rows: number[][] = [];
let start = 0;
if (m.type === 'loyalty_club' && count % 2 === 1) {
rows.push([0]);
start = 1;
}
for (let i = start; i < count; i += 2) rows.push(idx.slice(i, i + 2));
return rows;
}
// Mriežka kariet s rovnakou výškou kariet v riadku
export function renderProductGrid(m: NewsletterModule, mode: RenderMode): string {
const products: CardProduct[] = m.data.products || [];
const oneColumn = cardContextForModule(m, mode).cardWidth > 300;
return gridRows(m, products.length, oneColumn)
.map((row, rIdx) => {
const spacer = rIdx > 0 ? '<tr><td height="12" style="font-size: 12px; line-height: 12px;">&nbsp;</td></tr>' : '';
const cells = row
.map(
(p, idx) => `
<td width="${cols === 1 ? 100 : 50}%" valign="top" height="1" style="${cols === 1 ? '' : idx === 0 ? 'padding-right: 6px;' : 'padding-left: 6px;'} height: 100%;">
${renderProductCard(p, ctx)}
(i, idx) => `
<td width="${row.length === 1 ? 100 : 50}%" valign="top" height="1" style="${row.length === 1 ? '' : idx === 0 ? 'padding-right: 6px;' : 'padding-left: 6px;'} height: 100%;">
${renderProductCard(products[i], cardContextFor(m, i, mode))}
</td>`
)
.join('');
const filler = cols === 2 && row.length === 1 ? '<td width="50%" style="padding-left: 6px;"></td>' : '';
// posledný riadok s 1 produktom v 2-stĺpcovej mriežke (bežné sekcie) – produkt ostane v ľavej polovici
const filler = !oneColumn && row.length === 1 && cardContextFor(m, row[0], mode).cardWidth <= 300 ? '<td width="50%" style="padding-left: 6px;"></td>' : '';
return `${spacer}
<tr>
<td>