--- phase: 03-miejsca-postojowe plan: 01 type: execute wave: 1 depends_on: [] files_modified: - wp-content/plugins/elementor-addon/elementor-addon.php - wp-content/plugins/elementor-addon/widgets/parking-spots.php - wp-content/plugins/elementor-addon/assets/js/main.js - wp-content/plugins/elementor-addon/assets/css/main.css autonomous: false --- ## Goal Stworzyc widget Elementor "Miejsca postojowe" wyswietlajacy ceny dwoch typow miejsc (zwykle i rodzinne) z przyciskiem "Historia cen" oraz popup, a takze rozszerzyc cron, AJAX i XML export o dane parkingowe. ## Purpose Deweloper musi prezentowac ceny miejsc postojowych na stronie oferty oraz raportowac je do dane.gov.pl zgodnie z ustawa o jawnosci cen. ## Output - Nowy widget Elementor: `Elementor_Parking_Spots` - Tabela DB: `wp_parking_price_history` - Rozszerzony cron o zapis cen parkingowych - Rozszerzony AJAX o historie cen parkingowych - Rozszerzony XML export o miejsca postojowe ## Project Context @.paul/PROJECT.md @.paul/ROADMAP.md @.paul/STATE.md ## Source Files @wp-content/plugins/elementor-addon/elementor-addon.php @wp-content/plugins/elementor-addon/widgets/apartaments.php @wp-content/plugins/elementor-addon/assets/js/main.js @wp-content/plugins/elementor-addon/assets/css/main.css ## Existing Patterns - Apartament widget: klasa Elementor_Apartaments w widgets/apartaments.php - Historia cen popup: globalny overlay #price-history-overlay, wypelniany przez AJAX - AJAX endpoint: wp_ajax_apartamenty_get_price_history → JSON {title, price, price_m2, history} - Cron: apartamenty_record_prices → INSERT IGNORE do wp_price_history - XML: apartamenty_generate_price_xml() → z per apartament - ACF: parking prices sa w opcjach ACF (options page), klucze do odkrycia w DB - Garage map: get_field('garage_spots', 'option') → parking-N → status No specialized flows configured. ## AC-1: Widget wyswietla ceny parkingowe ```gherkin Given widget "Miejsca postojowe" jest dodany na stronie w Elementorze When uzytkownik otwiera strone Then widzi sekcje z dwoma typami: "Miejsce postojowe zwykle" i "Miejsce postojowe Rodzinne" And kazdy typ ma wyswietlona aktualna cene z ACF And kazdy typ ma przycisk "HISTORIA CEN" ``` ## AC-2: Popup historia cen dziala dla miejsc postojowych ```gherkin Given uzytkownik widzi widget miejsc postojowych When klika przycisk "HISTORIA CEN" przy dowolnym typie Then otwiera sie popup z aktualna cena i tabela historii zmian cen And popup zamyka sie przyciskiem X, klikajac overlay lub klawiszem Escape ``` ## AC-3: Cron zapisuje ceny parkingowe codziennie ```gherkin Given WP Cron jest zaplanowany When uruchamia sie dzienne zadanie Then aktualne ceny obu typow miejsc postojowych sa zapisywane do wp_parking_price_history And zapis jest idempotentny (INSERT IGNORE, jeden rekord na typ na dzien) ``` ## AC-4: XML export zawiera miejsca postojowe ```gherkin Given endpoint /ceny-mieszkan.xml jest dostepny When uzytkownik pobiera XML Then XML zawiera sekcje z oboma typami And kazdy typ ma aktualna cene i historie zmian ``` Task 1: Odkryj klucze ACF dla cen parkingowych i stworz tabele DB + cron + AJAX wp-content/plugins/elementor-addon/elementor-addon.php 1. **Odkryj ACF meta keys** — sprawdz w bazie (wp_options) jakie klucze ACF sa uzywane dla cen miejsc postojowych. Prawdopodobnie sa w opcjach ACF (get_field z 'option'). Poszukaj kluczy zawierajacych "parking", "postojow", "garage_price" lub podobnych. 2. **Stworz tabele wp_parking_price_history:** ```sql CREATE TABLE wp_parking_price_history ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, parking_type VARCHAR(50) NOT NULL, -- 'zwykle' lub 'rodzinne' price VARCHAR(50) NOT NULL DEFAULT '', recorded_at DATE NOT NULL, UNIQUE KEY unique_daily (parking_type, recorded_at), KEY idx_type (parking_type) ) ``` - Dodaj funkcje tworzaca tabele analogicznie do elementor_addon_create_price_history_table() - Zaktualizuj elementor_addon_maybe_update_db() — zmien wersje DB na '1.1' 3. **Rozszerz cron** — w elementor_addon_record_prices() dodaj po petli apartamentow: - Pobierz ceny parkingowe z ACF options (odkryte klucze) - INSERT IGNORE do wp_parking_price_history dla kazdego typu 4. **Dodaj AJAX endpoint** — nowa funkcja `elementor_addon_get_parking_price_history_ajax()`: - Akcja: wp_ajax_parking_get_price_history / wp_ajax_nopriv_parking_get_price_history - Parametr: parking_type ('zwykle' lub 'rodzinne') - Zwraca: JSON {type_label, price, history: [{recorded_at, price}]} - Uzywa tego samego nonce co apartamenty 5. **Rozszerz XML** — w apartamenty_generate_price_xml() po zamknieciu ... nie, lepiej: - Zmien root element na opakowujacy i nowy - LUB dodaj wewnatrz (prostsze) - Kazdy typ: , , - Wyczysc transient po aktualizacji Avoid: - NIE zmieniaj istniejacego schematu wp_price_history (apartamenty) - NIE usuwaj istniejacych endpointow XML — rozszerzaj - Tabela wp_parking_price_history istnieje po aktywacji/upgrade - Reczne wywolanie crona zapisuje rekordy parkingowe - AJAX endpoint zwraca poprawny JSON - XML zawiera sekcje miejsca_postojowe AC-3 i AC-4 satisfied: cron zapisuje ceny, XML eksportuje miejsca postojowe Backend: tabela DB, cron, AJAX endpoint, XML export dla miejsc postojowych 1. Sprawdz w wp-admin > Narzedzia > Jawnosc Cen czy XML zawiera miejsca postojowe 2. Otworz /ceny-mieszkan.xml w przegladarce i sprawdz sekcje miejsca_postojowe 3. Potwierdz ze ACF klucze zostaly poprawnie odkryte Type "approved" to continue to widget, or describe issues Task 2: Stworz widget Elementor "Miejsca postojowe" z przyciskiem historia cen wp-content/plugins/elementor-addon/widgets/parking-spots.php, wp-content/plugins/elementor-addon/assets/js/main.js, wp-content/plugins/elementor-addon/assets/css/main.css, wp-content/plugins/elementor-addon/elementor-addon.php 1. **Stworz widgets/parking-spots.php** — klasa Elementor_Parking_Spots: - get_name() → 'parking_spots' - get_title() → 'Miejsca Postojowe' - get_style_depends / get_script_depends → te same co apartaments - render(): a) Pobierz ceny z ACF options (odkryte klucze) b) Wyrenderuj dwie karty: "Miejsce postojowe zwykle" i "Miejsce postojowe Rodzinne" c) Kazda karta: nazwa typu, cena, przycisk "HISTORIA CEN" z data-parking-type="zwykle/rodzinne" d) Uzyj stylistyki zblizonej do apartament-card__info (tabela z cenami) e) Wyrenderuj ten sam popup overlay co apartamenty (reuse #price-history-overlay) — popup juz istnieje globalnie, wiec NIE renderuj go ponownie jesli jest na tej samej stronie — dodaj warunek: renderuj popup tylko jesli nie ma go jeszcze w DOM 2. **Zarejestruj widget** w elementor-addon.php: - W register_hello_world_widget() dodaj require + register dla Elementor_Parking_Spots 3. **Rozszerz main.js** — dodaj obsluge klikniecia .btn-parking-historia-cen: - Analogicznie do .btn-historia-cen ale wysyla parking_type zamiast post_id - Uzywa akcji 'parking_get_price_history' - Wypelnia ten sam popup (reuse) - Tabela historii: data, cena (bez ceny/m2 — uproszczona) 4. **Rozszerz main.css** — dodaj style dla widgetu parkingowego: - Klasa .parking-spots z kartami - Styl zbliżony do apartament-card ale uproszczony (bez galerii, dokumentow) - Responsive Avoid: - NIE duplikuj popupa historia cen — uzyj istniejacego - NIE zmieniaj stylow apartamentow - NIE dodawaj Swipera/FancyBoxa — widget parkingowy ich nie potrzebuje - Widget pojawia sie w panelu Elementor w kategorii "basic" - Po dodaniu na strone wyswietla dwa typy z cenami - Klikniecie "Historia cen" otwiera popup z danymi AC-1 i AC-2 satisfied: widget wyswietla ceny, popup historia cen dziala Widget Elementor "Miejsca Postojowe" z historia cen — design wg Figma Frame 16 1. Otworz Elementor na stronie /apartamenty/ lub testowej 2. Dodaj widget "Miejsca Postojowe" 3. Sprawdz czy wyswietla dwa typy z cenami 4. Kliknij "Historia cen" — sprawdz popup 5. Porownaj z designem na Figmie (Frame 16) 6. Sprawdz responsywnosc (mobile) Type "approved" or describe visual/functional issues ## DO NOT CHANGE - wp-content/plugins/elementor-addon/widgets/apartaments.php (widget apartamentow stabilny) - wp-content/themes/hello-elementor/template-parts/garage-map.php (mapa garazowa) - Istniejacy schemat tabeli wp_price_history (nie modyfikuj kolumn) - Istniejace endpointy XML — rozszerzaj, nie usuwaj ## SCOPE LIMITS - Tylko dwa typy miejsc postojowych: zwykle i rodzinne - Brak galerii/dokumentow w widgecie parkingowym - Brak edycji cen w widgecie — ceny z ACF options - Strona admina Jawnosc Cen — nie modyfikuj (XML sam sie rozszerzy) Before declaring plan complete: - [ ] Widget "Miejsca Postojowe" renderuje dwa typy z cenami ACF - [ ] Przycisk "Historia cen" otwiera popup z danymi z AJAX - [ ] Cron zapisuje ceny parkingowe do wp_parking_price_history - [ ] /ceny-mieszkan.xml zawiera sekcje z miejscami postojowymi - [ ] Brak bledow PHP (WP_DEBUG=true) - [ ] Istniejace funkcjonalnosci apartamentow nie naruszone - [ ] All acceptance criteria met - All tasks completed - All verification checks pass - No PHP errors or warnings introduced - Widget dostepny w Elementor i poprawnie renderuje - Historia cen popup dziala identycznie jak dla apartamentow - XML export zawiera miejsca postojowe z historia After completion, create `.paul/phases/03-miejsca-postojowe/03-01-SUMMARY.md`