---
phase: 03-products-all-campaigns-view
plan: 01
subsystem: ui
tags: [select2, jquery, products, filter, frontend]

requires:
  - phase: (none)
    provides: istniejący szablon /products oraz backend z `build_scope_filters` obsługującym już campaign_id ≤ 0

provides:
  - Widoczna opcja "- wszystkie kampanie -" w filtrze kampanii na /products po każdej selekcji
  - Widoczna opcja "- wszystkie grupy -" w filtrze grup reklam na /products po każdej selekcji
  - Przywrócony widok zagregowany bez konieczności czyszczenia localStorage / zmiany klienta

affects:
  - Każda przyszła zmiana w filtrach Select2 na /products (np. dodanie kolejnych filtrów ze scope)
  - Ewentualne rozszerzenia filtrów analogicznych na innych stronach (sugerowane: /campaigns, jeśli używa podobnego wzorca Select2 z placeholderem + allowClear)

tech-stack:
  added: []
  patterns:
    - "Select2 z pustą opcją default: nie używać `placeholder` + `allowClear` jednocześnie, jeśli pierwsza <option value=''> ma być dostępna w dropdownie (Select2 chowa ją jako placeholder)"

key-files:
  created: []
  modified:
    - templates/products/main_view.php

key-decisions:
  - "Usunięcie `placeholder` i `allowClear` zamiast wprowadzania sentinel value='0' — minimalny blast radius, brak zmian w handlerach i backendzie"

patterns-established:
  - "W szablonach z filtrami Select2, gdzie <option value=''> reprezentuje widok 'wszystkie', nie konfigurować placeholdera Select2 — żeby opcja pozostała widoczna w dropdownie po selekcji"

duration: ~25min
started: 2026-04-24T23:00:00+02:00
completed: 2026-04-24T23:25:00+02:00
---

# Phase 3 Plan 01: Products — widok "wszystkie kampanie" (Summary)

**Przywrócono możliwość powrotu do zagregowanego widoku produktów (wszystkie kampanie / wszystkie grupy reklam) na stronie /products — pojedynczym kliknięciem w dropdown, bez czyszczenia localStorage.**

## Performance

| Metric | Value |
|--------|-------|
| Duration | ~25 min (PLAN + APPLY + UNIFY) |
| Started | 2026-04-24T23:00:00+02:00 |
| Completed | 2026-04-24T23:25:00+02:00 |
| Tasks | 2 z 2 (1 auto + 1 human-verify) |
| Files modified | 1 |

## Acceptance Criteria Results

| Criterion | Status | Notes |
|-----------|--------|-------|
| AC-1: Powrót do "wszystkie kampanie" po wyborze kampanii | Pass | Zweryfikowane w przeglądarce: opcja widoczna w dropdownie, tabela przeładowuje zagregowany widok, panele boczne chowane |
| AC-2: Powrót do "wszystkie grupy" po wyborze grupy reklam | Pass | Zweryfikowane: przycisk "Usuń grupę reklam" wyszarzony, tabela wraca do pełnego widoku kampanii |
| AC-3: Stan zachowany w localStorage po F5 | Pass | Po reloadzie oba dropdowny pokazują "- wszystkie … -", brak błędów w konsoli |
| AC-4: Brak regresji w istniejących przepływach | Pass | Filtry tekstowe, sortowanie, paginacja, edycja inline CL1/CL4/min_roas, usuwanie grup SHOPPING — wszystko działa |

## Accomplishments

- Znalezienie i naprawa nieoczywistej interakcji Select2: `placeholder` + `allowClear` ukrywa pierwszą `<option value="">` jako placeholder, co odbiera użytkownikowi możliwość powrotu do agregatu po selekcji.
- Zmiana ograniczona do **1 pliku, 4 linii** — bez dotykania kontrolera, factory, migracji, innych szablonów ani CSS.
- Zero regresji w pozostałych przepływach UI na /products (zweryfikowane w checkpoint human-verify wg AC-4).

## Task Commits

Nie wykonano jeszcze commita — commit wykona użytkownik ręcznie lub osobnym poleceniem (projekt używa FTP sync do produkcji, patrz `.vscode/ftp-kr.sync.cache.json`).

| Task | Commit | Type | Description |
|------|--------|------|-------------|
| Task 1: Fix Select2 config w init_products_scope_select_search | (pending) | fix | Usunięto `placeholder: '- wybierz -'` i `allowClear: true` z konfiguracji Select2 dla filtrów kampanii/grup reklam |
| Task 2: Human-verify w przeglądarce | n/a | n/a | Zatwierdzone: "approved" |

Sugerowany komunikat commita: `fix(products): przywróć widok "wszystkie kampanie" w filtrze /products`

## Files Created/Modified

| File | Change | Purpose |
|------|--------|---------|
| `templates/products/main_view.php` | Modified (+1 / −3, linie 523–527) | Uproszczono konfigurację Select2 w `init_products_scope_select_search()` — pozostaje tylko `width: '100%'` |

## Decisions Made

| Decision | Rationale | Impact |
|----------|-----------|--------|
| Usunięcie `placeholder` i `allowClear` zamiast wprowadzenia `value="0"` dla opcji "wszystkie" | Minimalny blast radius: brak zmian w handlerach `change`, brak zmian w backendzie, brak zmian w localStorage; zgodne z istniejącym kontraktem `(int)$campaign_id` w `build_scope_filters` | Przyszłe filtry typu "wszystkie" na /products powinny stosować ten sam wzorzec: pusta `<option value="">` + brak placeholdera w Select2 |

## Deviations from Plan

### Summary

| Type | Count | Impact |
|------|-------|--------|
| Auto-fixed | 0 | — |
| Scope additions | 0 | — |
| Deferred | 0 | — |
| Wording / verify delta | 1 | Kosmetyczna różnica w verify (patrz niżej), brak wpływu funkcjonalnego |

**Total impact:** Plan wdrożony 1:1, jedna kosmetyczna różnica w kryterium `verify` bez wpływu na AC.

### Auto-fixed Issues

Brak.

### Wording / Verify delta

**1. Verify wording: `grep allowClear` → brak trafień (plan) vs 1 trafienie (actual)**
- **Found during:** Task 1 verify
- **Issue:** Plan oczekiwał, że po zmianie `grep -n allowClear templates/products/main_view.php` zwróci 0 trafień. Faktycznie zwrócił 1 (linia 2097).
- **Diagnoza:** Linia 2097 należy do Google taxonomy category pickera w modalu edycji produktu (`$googleCategory.select2({...})` wewnątrz `loadGoogleCategories`) — niezwiązany feature, poza zakresem planu.
- **Fix:** Nie wymagany. In-scope init (`init_products_scope_select_search`, linie 523–525) jest czysty. Plan miał za szeroki pattern; intencja (brak `allowClear` w filtrach scope) została zrealizowana.
- **Verification:** Ręczna weryfikacja wiersza 2097 — kontekst to `loadGoogleCategories`, nie filtry /products.

### Deferred Items

Brak.

## Issues Encountered

Brak. Plan wdrożony 1:1.

## Next Phase Readiness

**Ready:**
- UI /products stabilne i kompletne pod kątem filtrów scope (klient → kampania → grupa → wszystkie/konkretne).
- Wzorzec "Select2 bez placeholdera dla agregatu" udokumentowany — można replikować na innych stronach z podobnymi filtrami.

**Concerns:**
- Pozostała instancja `allowClear: true` w `loadGoogleCategories` (linia 2097) jest nietknięta — to inny feature, ale warto mieć świadomość, że ten sam wzorzec Select2 stosowany jest w projekcie w dwóch miejscach.
- Deploy na produkcję wymaga FTP sync szablonu + hard reload w przeglądarce klienta (Ctrl+Shift+R) ze względu na cache JS.

**Blockers:** Brak.

---
*Phase: 03-products-all-campaigns-view, Plan: 01*
*Completed: 2026-04-24*
