Plan 02-03: Customization save + success modal (5/5 AC)
- 26-field squaremeter POST payload (verbose PL dim, qty_alt/qty_alth)
- Chain POST /module/ps_shoppingcart/ajax -> Bootstrap #blockcart-modal
- Critical fix: moved {/block} so inline script actually renders
- __p02p02InFlight re-entrancy guard
Plan 02-04: Live cena per-sqm label obok "Dodaj do koszyka" (5/5 AC)
- .p02p04-total-price label, gorna .current-price static
- Separate __p02p04Bound + setInterval reconciliation
- Poll-retry prestashop.on registration
Plan 02-05: Struktura materialu w POST payload (4/4 AC)
- Enumerate [name^="group["] spoza formy, doklej do payload
- Fix: group_5 select w .product-bar-box nie trafial do koszyka
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
7.7 KiB
7.7 KiB
PROJECT.md
Name
newwalls.pl — PrestaShop 1.7 (theme: ayon)
Mission
Sklep z tapetami na wymiar. Klient prowadzi migrację wyglądu strony produktu na nowy layout. Do czasu zakończenia testów nowy layout jest warunkowany IP administratora.
Core Constraints
- Stary i nowy wygląd strony produktu współegzystują w
themes/ayon/templates/catalog/product.tpl:- Stary layout:
{if $smarty.server.REMOTE_ADDR != '89.69.31.86'} ... {/if} - Nowy layout:
{if $smarty.server.REMOTE_ADDR == '89.69.31.86'} ... {/if}
- Stary layout:
- Nie wolno modyfikować starego layoutu (produkcja działa dla zwykłych użytkowników).
- Partial
themes/ayon/templates/catalog/_partials/product-variants.tpljest współdzielony — zmiany w nim muszą być zgodne z oboma layoutami. - Stack: PrestaShop 1.7, Smarty, jQuery, SCSS (
themes/ayon/assets/css/custom.scss→custom.css).
Value Proposition
Nowy layout strony produktu ma dać czystszy, bardziej prezentowalny UI konfiguratora tapety przy zachowaniu dotychczasowej funkcjonalności (wybór wariantu kolorystycznego, wymiary, dodanie do koszyka itd.).
Known Broken After Redesign
✅ Naprawione (Phase 01)
.product-variants(wariant kolorystyczny) — wygląd grid 3×1 wg Figma 27:9867 + klik zmienia wariant in-place (AJAXaction=refresh+history.pushState).
✅ Naprawione (Phase 02)
- Konfigurator „piece" (Plan 02-01) — crop + odbicie lustrzane, drag + mirror, re-init po AJAX refresh. Reuse
#piecez shared partial. - Add-to-cart submission (Plan 02-02) — capture-phase native handler w custom.js + inline mirror, blockcart refresh, idempotency guard. Button+qty poza formą
#add-to-cart-or-refresh— manualny serialize + POST. - Customization save + success modal (Plan 02-03) — full squaremeter payload (26 fields, verbose PL dim), chain POST do
/module/ps_shoppingcart/ajax→ Bootstrap#blockcart-modal.__p02p02InFlightre-entrancy guard. Inline script finally renders (Plan 02-03{/block}move). - Live cena labelka (Plan 02-04) —
.p02p04-total-priceobok "Dodaj do koszyka", reactively updates z piece dimensions + variant AJAX refresh. Górna.current-pricezostaje statyczna info-label. - Struktura materiału w POST payload (Plan 02-05) — enumeracja external PS attribute groups (
[name^="group["]poza formą) w POST payload. Wybrana „Tekstura materiału" (<select id="group_5">) trafia do koszyka z prawidłowymid_product_attribute.
⚠️ Do naprawy (Phase 03+ / deferred)
- Plan 02-06 (deferred nice-to-have) — systemowy cache-buster
?v=<mtime>dla<script src=custom.js>; pozwoli wycofac inline mirror z Plan 02-02/02-03/02-04/02-05. - Plan 02-07 — Puste bloki
<div class="product-box--data"></div>:product-protect,product-installation,product-order-sample— wypełnić treścią. - Brakujące elementy dla pełnego PS
updatedProductflow (.product-cover-thumbnails,.js-product-images2-modal,.product-details,.product-customization,.product-additional-info) — edge case'y przy zmianie wariantu z różnymi miniaturami/opisami. - Resize handles bezpośrednio na
#piece(deferred bonus z Plan 02-01).
Established Patterns (Phase 01)
- Scoped CSS under
body#product .product-variants-data--new— izoluje zmiany nowego layoutu od globalnych reguł i starego widoku. - Własny AJAX refresh w
custom.js—action=refresh(nieproductrefresh), POST nawindow.location.href.split('?')[0].split('#')[0],dataType: 'json', headerAccept: application/json. - In-place DOM update:
history.pushState(resp.product_url)+$('.product-prices-data .product-prices').replaceWith(resp.product_prices)+$('.product_image_wrapper').html(resp.product_cover_thumbnails)+prestashop.emit('updatedProduct', resp). Fallback nawindow.location.reload()przy błędzie. - Pipeline SCSS → CSS: edytuj tylko
themes/ayon/assets/css/custom.scss,custom.cssauto-generowany przez user'a watcher (feedback memory).
Established Patterns (Phase 02)
- Capture-phase native addEventListener +
useCapture=true— blokuje PS core delegated handlers (bubble phase) w customowym flow, gdy trzeba całkowicie nadpisać PS behavior (Plan 02-02). - Idempotency guard per Plan (
__p02pNNBound) — kazdy plan ma own flag, nie shared; chroni inline mirror przed blokada gdy custom.js cached stale. Separate guards pozwalaja na plan-level cache-aware deployment (Plan 02-02/03/04). - Re-entrancy flag (
__pNNInFlight) — chroni przed podwójnym POST gdy handler i inline mirror oba firują. Reset wcomplete:callback jQuery.ajax (Plan 02-03). - Inline mirror IIFE w
{block name='content'}—<script>wewnatrz Smarty block, cache-safety dopóki systemowego cache-bustera (Plan 02-05) nie ma.{/block}musi zamykac się PO script (Plan 02-03 critical fix). - Playwright MCP ground truth capture — temporary flip IP gate → capture 26-field OLD payload przed portowaniem do NEW (Plan 02-03). Bez tego verbose PL dim format i
qty_alt/qty_althby zostaly pominiete. - Manual FTP deploy via
curl -T ftp://...— ftp-kr VSCode watcher nie łapie zmian Claude Code Edit tool (feedback memory). Deploy 226 confirmation per file. - Poll-retry dla late globals (
prestashop, itp.) — inline script runtime,window.prestashopmoze jeszcze nie istniec.(function fn(){ if (avail) register(); else setTimeout(fn, 200); })()niezawodnie obsługuje race (Plan 02-04). - Synchronous IIFE init zamiast jQuery(document).ready — ready nie firuje konsekwentnie w inline Smarty block context. Synchronous call + recalc-safe early-return pokrywa DOM-not-ready case (Plan 02-04).
- setInterval reconciliation gdy external code overwritea nasz DOM po initial render (np. squaremeter init). 10×500ms okno = 5s pokrycie (Plan 02-04).
- External PS attribute groups enumeration —
[name^="group["]inputs spoza#add-to-cart-or-refreshmuszą być ręcznie enumerowane i dołączane do payload ($form.serialize()ich nie łapie). Defensiveclosest('#form').lengthskip (unika duplicate gdy kiedyś przesunięte do formy) + filter radio/checkbox przez:checked(Plan 02-05).
Key Decisions (aggregated)
| Data | Faza/Plan | Decyzja | Wpływ |
|---|---|---|---|
| 2026-04-23 | 01-01 | Własny AJAX action=refresh + history.pushState zamiast PS core productrefresh |
In-place wariant switch bez reload; base pattern dla wszystkich subsequent AJAX updates w NEW layoucie |
| 2026-04-23 | 02-01 | Override totalpriceinfospecific/prod na no-op |
Spowodowało regresję squaremeter customization flow (Plan 02-02/03 fix); no-op zostaje ale fields syncowane manualnie w POST |
| 2026-04-23 | 02-02 | Capture-phase native handler (useCapture=true) | Pattern dla blokowania PS core bubble handlers przy customowym flow |
| 2026-04-23 | 02-02 | Inline mirror IIFE w product.tpl | Cache-safety dopóki Plan 02-05 nie dostarczy systemowego cache-bustera |
| 2026-04-24 | 02-03 | Playwright capture z flipped IP → ground truth payload | Bez tego verbose PL dim format + fields (qty_alt/qty_alth/calculated_total itp.) zostałyby pominięte; dał 5/5 AC pass |
| 2026-04-24 | 02-03 | Move {/block} inside script wrapper |
Krytyczne: Smarty {extends} renderuje TYLKO blocki; inline script z Plan 02-02 był dead code przez cały czas |
| 2026-04-24 | 02-04 | Scope pivot: label zamiast .current-price |
User request mid-task; górna cena zostaje info-label, konkretna suma blisko buttona |
| 2026-04-24 | 02-04 | Poll-retry prestashop.on + separate __p02p04Bound | Late-loading globals + stale-cache safety |
| 2026-04-24 | 02-05 | Enumerate [name^="group["] spoza formy → payload |
Future-proof: kolejne PS attribute groups pokryte automatycznie bez code change |
Last updated: 2026-04-24 after Phase 02 (5 plans)