--- phase: 02-product-actions-fixes plan: 01 subsystem: ui tags: [prestashop, smarty, jquery, scss, piece, crop, fancybox, module-hook-compat] requires: - phase: 01-product-variants-fix provides: - Form `
` w gałęzi nowego layoutu — Plan 02-01 dołącza do niej 8 hidden inputs dla crop/mirror - Marker class `.product-variants-data--new` — Plan 02-01 wykorzystuje do scope'u JS init (`setTimeout` check) - Własny AJAX refresh w custom.js (`action=refresh` + in-place DOM update) — Plan 02-01 dopina listener `prestashop.on('updatedProduct')` do re-bindowania dragElement po replace `.product_image_wrapper` provides: - Działający konfigurator „piece" (wybór fragmentu tapety) w nowym layoucie: popup trigger w `.product-size-data`, fancybox z input'ami Szerokość/Wysokość, piece overlay na zdjęciu - 8 hidden inputów `is_crop`, `is_reflection`, `crop_pos_x/y`, `crop_width/height`, `piece_bg_top/left` w formie `#add-to-cart-or-refresh` (nowy layout) - Defensive setup (no-op override `totalpriceinfospecific`/`prod` + DOM stubs w custom.js) — unblocks istniejące piece handlery w nowym layoucie bez modyfikacji inline-scriptów z module hooks affects: - Plan 02-02 (add-to-cart) — hidden inputs już w formie, gotowe do POST'owania do koszyka. Także no-op override `totalpriceinfospecific` oznacza że logika cen wymaga innego mechanizmu w nowym layoucie. - Plan 02-03 (empty blocks) — pattern scope'owania CSS pod `.product-size-data .product-size-data--new` do reużycia dla `.product-protect`, `.product-installation`, `.product-order-sample` tech-stack: added: [] patterns: - "Shared partial reuse: zamiast duplikować element między layoutami, reużyć istniejący (#piece z product-cover-thumbnails.tpl)" - "No-op override globalnych funkcji z module hook (`totalpriceinfospecific`, `prod`) jako alternative do modyfikacji inline-scriptów których nie można zmienić" - "DOM stubs injection via JS zamiast template — obchodzi Smarty cache + FTP sync delay" - "setTimeout(600) init zamiast `$(document).ready` — defer poza queue ready callbacków które crash'ują na brakujących DOM elementach w nowym layoucie" key-files: created: - .paul/phases/02-product-actions-fixes/02-01-PLAN.md - .paul/phases/02-product-actions-fixes/02-01-SUMMARY.md modified: - themes/ayon/templates/catalog/product.tpl - themes/ayon/assets/js/custom.js - themes/ayon/assets/css/custom.scss key-decisions: - "`#piece` reużywany z product-cover-thumbnails.tpl — nie duplikujemy w product.tpl" - "totalpriceinfospecific / prod override'owane na no-op w nowym layoucie (crash z powodu brakujących DOM deps)" - "DOM stubs injection w JS zamiast template (cache/sync unreliability)" - "Piece NIE auto-init'uje się — pojawia się dopiero po kliknięciu popup trigger (user feedback w checkpoint)" - "Defensive guard `.pp_stick_parent` w click handler (element exists only w starym layoucie)" patterns-established: - "Scope'owanie CSS dla bloków nowego layoutu: `body#product . .--new {...}` — wzór do reużycia dla kolejnych bloków (product-protect, product-installation, etc.)" - "Obrona przed cross-layout breakage module hooków: setTimeout init w custom.js z no-op override + DOM stubs; nie ruszamy inline-scriptów" - "Reużywanie state holders jako hidden inputów: `` zamiast tworzenia osobnego state-management, istniejące handlery bindują się do ID identycznych ze starym layoutem" duration: ~3.5h (z live debug'iem via Playwright) started: 2026-04-23T19:30:00Z completed: 2026-04-23T22:30:00Z --- # Phase 02 Plan 01: Piece/crop configurator (nowy layout) — Summary **Port konfiguratora „piece" (wybór fragmentu tapety + mirror) do nowego layoutu z zachowaniem pełnego kontraktu serializacji do koszyka. Popup trigger + fancybox — odzwierciedla user flow starego layoutu.** ## Performance | Metric | Value | |--------|-------| | Duration | ~3.5h | | Started | 2026-04-23T19:30:00Z | | Completed | 2026-04-23T22:30:00Z | | Tasks | 3 auto + 1 checkpoint (approved po iteracji) | | Files modified | 3 source + 2 PAUL meta | ## Acceptance Criteria Results | Criterion | Status | Notes | |-----------|--------|-------| | AC-1: Markup piece + mirror w nowym layoucie | Pass | `#piece` reużyty z shared partial (nie duplikowany), controls w `.product-size-data .product-box--data`, 8 hidden inputów w `#add-to-cart-or-refresh`. Initial text „Wybierz rozmiar" (zamiast stałego „100x100" per user feedback). | | AC-2: Piece interaktywny | Pass | Popup otwiera się po kliknięciu `.piece-summary`, zmiana wymiarów w popup → piece rescale (100x100 → 200x150 = 40%×50% kontenera), hidden inputs `#product_crop_width/height` sync'ują. Drag działa (dragElement z istniejącego flow). Verified via Playwright. | | AC-3: Form serialization | Pass | `$('#add-to-cart-or-refresh').serialize()` zwraca pełny ciąg: `token=...&id_product=...&id_customization=...&is_crop=1&is_reflection=0&crop_pos_x=200&crop_pos_y=100&crop_width=200&crop_height=150&piece_bg_top=-104.398&piece_bg_left=-208.804&group[4]=6`. Wszystkie pola aktualne. | | AC-4: Re-init po zmianie wariantu | Not tested | AC zakładał re-bind dragElement po `updatedProduct`. Listener dodany (custom.js:681-692), ale live test zmiany wariantu nie przeprowadzony w tej sesji. Markowane jako "not verified" — do re-verify w Plan 02-02 lub osobno. | | AC-5: Zero regresji w starym layoucie | Not tested | Stary layout (IP != 89.69.31.86) nie był testowany w tej sesji. Zmiany w custom.js (no-op override, setTimeout init, stubs injection) są scope'owane do nowego layoutu via `$('.product-variants-data--new').length` check — nie powinny dotknąć starego. Do weryfikacji przed commitowaniem phase. | **Modyfikacja AC:** Plan pierwotnie zakładał piece auto-init'ujący się na load (inline `