Download all files FTP

This commit is contained in:
2026-04-13 15:50:16 +02:00
parent d8382136b2
commit cb5b386424
6906 changed files with 1956223 additions and 40713 deletions

View File

@@ -12,7 +12,7 @@ Użytkownicy mogą przeglądać na stronie ofertę dewelopera.
| Attribute | Value |
|-----------|-------|
| Version | 0.1.0 |
| Version | 0.2.0 |
| Status | Released |
| Last Updated | 2026-03-12 |
@@ -30,6 +30,13 @@ Użytkownicy mogą przeglądać na stronie ofertę dewelopera.
- (brak — gotowy na nowy milestone)
### Validated (Shipped) — v0.2
- [x] Widget Elementor wyświetla ceny miejsc postojowych (zwykłe i rodzinne) — v0.2
- [x] Popup historia cen dla miejsc postojowych (reuse apartamentów) — v0.2
- [x] Cron zapisuje ceny parkingowe codziennie do wp_parking_price_history — v0.2
- [x] XML /ceny-mieszkan.xml zawiera sekcję <miejsca_postojowe> — v0.2
### Planned (Next)
- (do zdefiniowania podczas następnego planowania)
@@ -72,4 +79,4 @@ Użytkownicy mogą przeglądać na stronie ofertę dewelopera.
---
*Created: 2026-03-12*
*Last updated: 2026-03-12 after v0.1 Initial Release*
*Last updated: 2026-03-25 after v0.2 Miejsca Postojowe*

View File

@@ -9,12 +9,23 @@ Strona internetowa dla dewelopera pozwalająca na okazanie oferty klientom. Proj
Brak aktywnego milestone.
Uruchom `/paul:discuss-milestone` lub `/paul:milestone` aby zdefiniować następny.
## Next Milestone
Uruchom `/paul:discuss-milestone` lub `/paul:milestone` aby zdefiniować.
## Completed Milestones
<details>
<summary>v0.2 Miejsca Postojowe - 2026-03-25 (1 faza)</summary>
| Phase | Name | Plans | Completed |
|-------|------|-------|-----------|
| 3 | Miejsca postojowe | 1/1 | 2026-03-25 |
**Kluczowe deliverables:**
- Widget Elementor "Miejsca Postojowe" (zwykłe + rodzinne)
- Historia cen z popup (reuse apartamentów)
- Cron dzienny zapis cen parkingowych (wp_parking_price_history)
- XML export rozszerzony o sekcję <miejsca_postojowe>
</details>
<details>
<summary>v0.1 Initial Release - 2026-03-12 (2 fazy)</summary>
@@ -31,4 +42,4 @@ Uruchom `/paul:discuss-milestone` lub `/paul:milestone` aby zdefiniować.
</details>
---
*Roadmap updated: 2026-03-12 after v0.1 Initial Release*
*Roadmap updated: 2026-03-25 after v0.2 Miejsca Postojowe*

View File

@@ -5,25 +5,27 @@
See: .paul/PROJECT.md (updated 2026-03-12)
**Core value:** Uzytkownik moze przegladac oferte dewelopera i sprawdzac historie cen
**Current focus:** Milestone v0.1 ukonczone — gotowy na nowy milestone
**Current focus:** Milestone v0.2 Miejsca Postojowe — ukonczone
## Current Position
Milestone: Awaiting next milestone
Phase: None active
Plan: None
Status: Milestone v0.1 Initial Release complete — ready for next
Last activity: 2026-03-12 — Milestone v0.1 completed
Milestone: v0.2 Miejsca Postojowe — Complete
Phase: [3] of [3] (Miejsca postojowe) — Complete
Plan: 03-01 complete
Status: Milestone v0.2 complete — ready for next
Last activity: 2026-03-25UNIFY 03-01 complete
Progress:
- v0.1 Initial Release: [██████████] 100% ✓
- v0.2 Miejsca Postojowe: [██████████] 100% ✓
- Phase 3: [██████████] 100% ✓
## Loop Position
Current loop state:
```
PLAN ──▶ APPLY ──▶ UNIFY
[Milestone complete — ready for next]
[Loop complete — milestone done]
```
## Accumulated Context
@@ -35,6 +37,9 @@ PLAN ──▶ APPLY ──▶ UNIFY
| INSERT IGNORE w cronie | Phase 1 | Jeden rekord na apt na dzien, idempotentny |
| XML jako czysty PHP string ENT_XML1 | Phase 2 | Brak zaleznosci od ext-dom |
| Transient 1h + inwalidacja przez cron | Phase 2 | Cache XML odswieza sie po kazdym cronie |
| ACF group access: get_field('grupa','option')['pole'] | Phase 3 | Parking ceny w grupach ACF |
| Osobna tabela wp_parking_price_history | Phase 3 | Separacja od apartamentow (parking_type vs post_id) |
| Cena m2 ukryta w widgecie parkingowym | Phase 3 | Dane nadal w cronie/XML, UI uproszczone |
### Deferred Issues
- Klient musi recznie zglosic URL /dane-gov-pl.xml do kontakt@dane.gov.pl
@@ -45,14 +50,13 @@ Brak.
## Session Continuity
Last session: 2026-03-12
Stopped at: Milestone v0.1 Initial Release ukonczone
Last session: 2026-03-25
Stopped at: Milestone v0.2 complete
Next action: /paul:discuss-milestone
Resume file: .paul/MILESTONES.md
Resume file: .paul/phases/03-miejsca-postojowe/03-01-SUMMARY.md
Resume context:
- v0.1 kompletny: historia cen (popup AJAX) + jawnosc cen (XML endpoints)
- Dokumentacja klienta: docs/readme.md + docs/jawnosc-cen.md
- Git tag v0.1.0 utworzony
- v0.2 kompletny: widget Miejsca Postojowe + historia cen + cron + XML
- Gotowy na nowy milestone
---
*STATE.md — Aktualizowany po kazdej istotnej akcji*

48
.paul/db_check.php Normal file
View File

@@ -0,0 +1,48 @@
<?php
$conn = new mysqli('host117523.hostido.net.pl', 'host117523_wyszynskiego12pagedevpl', 'yZs52KdErtTk9KmZ8XGq', 'host117523_wyszynskiego12pagedevpl');
if ($conn->connect_error) { die('Blad: ' . $conn->connect_error); }
echo "=== APARTAMENTY + ACF price fields ===\n";
$sql = "SELECT p.ID, p.post_title, pm.meta_key, pm.meta_value
FROM wp_posts p
JOIN wp_postmeta pm ON p.ID = pm.post_id
WHERE p.post_type = 'apartamenty'
AND p.post_status = 'publish'
AND pm.meta_key = 'information'
ORDER BY p.post_title LIMIT 5";
$r = $conn->query($sql);
while($row = $r->fetch_assoc()) {
echo $row['ID'] . ' | ' . $row['post_title'] . "\n";
$data = maybe_unserialize($row['meta_value']);
if (is_array($data)) {
echo " price: " . ($data['price'] ?? 'brak') . "\n";
echo " price_m2: " . ($data['price_m2'] ?? 'brak') . "\n";
} else {
echo " raw: " . substr($row['meta_value'], 0, 300) . "\n";
}
}
echo "\n=== WSZYSTKIE meta_key dla apartamentu ===\n";
$sql2 = "SELECT DISTINCT pm.meta_key
FROM wp_posts p
JOIN wp_postmeta pm ON p.ID = pm.post_id
WHERE p.post_type = 'apartamenty'
AND p.post_status = 'publish'
ORDER BY pm.meta_key";
$r2 = $conn->query($sql2);
while($row = $r2->fetch_row()) { echo $row[0] . "\n"; }
$conn->close();
function maybe_unserialize($data) {
if (is_serialized($data)) return unserialize($data);
return $data;
}
function is_serialized($data) {
if (!is_string($data)) return false;
$data = trim($data);
if ('N;' === $data) return true;
if (strlen($data) < 4) return false;
if (':' !== $data[1]) return false;
return (bool) preg_match('/^([adObis]):/', $data);
}

21
.paul/db_check2.php Normal file
View File

@@ -0,0 +1,21 @@
<?php
$conn = new mysqli('host117523.hostido.net.pl', 'host117523_wyszynskiego12pagedevpl', 'yZs52KdErtTk9KmZ8XGq', 'host117523_wyszynskiego12pagedevpl');
if ($conn->connect_error) { die('Blad: ' . $conn->connect_error); }
echo "=== APARTAMENTY z ceną ===\n";
$sql = "SELECT p.ID, p.post_title,
MAX(CASE WHEN pm.meta_key = 'information_price' THEN pm.meta_value END) as price,
MAX(CASE WHEN pm.meta_key = 'information_price_m2' THEN pm.meta_value END) as price_m2,
MAX(CASE WHEN pm.meta_key = 'information_floor_space' THEN pm.meta_value END) as floor_space
FROM wp_posts p
JOIN wp_postmeta pm ON p.ID = pm.post_id
WHERE p.post_type = 'apartamenty'
AND p.post_status = 'publish'
GROUP BY p.ID, p.post_title
ORDER BY p.post_title LIMIT 10";
$r = $conn->query($sql);
while($row = $r->fetch_assoc()) {
echo $row['ID'] . ' | ' . $row['post_title'] . ' | price: ' . $row['price'] . ' | price_m2: ' . $row['price_m2'] . ' | m2: ' . $row['floor_space'] . "\n";
}
$conn->close();

View File

@@ -0,0 +1,256 @@
---
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
---
<objective>
## 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
</objective>
<context>
## 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() → <lokale> z <lokal> 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
</context>
<skills>
No specialized flows configured.
</skills>
<acceptance_criteria>
## 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 <miejsca_postojowe> z oboma typami
And kazdy typ ma aktualna cene i historie zmian
```
</acceptance_criteria>
<tasks>
<task type="auto">
<name>Task 1: Odkryj klucze ACF dla cen parkingowych i stworz tabele DB + cron + AJAX</name>
<files>wp-content/plugins/elementor-addon/elementor-addon.php</files>
<action>
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 </lokale>... nie, lepiej:
- Zmien root element na <nieruchomosci> opakowujacy <lokale> i nowy <miejsca_postojowe>
- LUB dodaj <miejsca_postojowe> wewnatrz <lokale> (prostsze)
- Kazdy typ: <miejsce_postojowe typ="zwykle">, <cena>, <historia_cen>
- Wyczysc transient po aktualizacji
Avoid:
- NIE zmieniaj istniejacego schematu wp_price_history (apartamenty)
- NIE usuwaj istniejacych endpointow XML — rozszerzaj
</action>
<verify>
- 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
</verify>
<done>AC-3 i AC-4 satisfied: cron zapisuje ceny, XML eksportuje miejsca postojowe</done>
</task>
<task type="checkpoint:human-verify" gate="blocking">
<what-built>Backend: tabela DB, cron, AJAX endpoint, XML export dla miejsc postojowych</what-built>
<how-to-verify>
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
</how-to-verify>
<resume-signal>Type "approved" to continue to widget, or describe issues</resume-signal>
</task>
<task type="auto">
<name>Task 2: Stworz widget Elementor "Miejsca postojowe" z przyciskiem historia cen</name>
<files>
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
</files>
<action>
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
</action>
<verify>
- 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
</verify>
<done>AC-1 i AC-2 satisfied: widget wyswietla ceny, popup historia cen dziala</done>
</task>
<task type="checkpoint:human-verify" gate="blocking">
<what-built>Widget Elementor "Miejsca Postojowe" z historia cen — design wg Figma Frame 16</what-built>
<how-to-verify>
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)
</how-to-verify>
<resume-signal>Type "approved" or describe visual/functional issues</resume-signal>
</task>
</tasks>
<boundaries>
## 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)
</boundaries>
<verification>
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
</verification>
<success_criteria>
- 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
</success_criteria>
<output>
After completion, create `.paul/phases/03-miejsca-postojowe/03-01-SUMMARY.md`
</output>

View File

@@ -0,0 +1,134 @@
---
phase: 03-miejsca-postojowe
plan: 01
subsystem: ui, api, database
tags: [elementor, acf, wp-cron, xml, ajax, parking]
requires:
- phase: 01-historia-cen
provides: price_history table, popup pattern, AJAX pattern, XML endpoint
- phase: 02-jawnosc-cen
provides: XML export structure, dane.gov.pl integration
provides:
- Elementor widget "Miejsca Postojowe" with price display and history popup
- wp_parking_price_history DB table
- Daily cron recording parking prices
- AJAX endpoint for parking price history
- XML export extended with parking spots
affects: []
tech-stack:
added: []
patterns: [ACF group field access pattern]
key-files:
created:
- wp-content/plugins/elementor-addon/widgets/parking-spots.php
modified:
- wp-content/plugins/elementor-addon/elementor-addon.php
- wp-content/plugins/elementor-addon/assets/js/main.js
- wp-content/plugins/elementor-addon/assets/css/main.css
key-decisions:
- "ACF groups: pola cen w grupach, nie flat — get_field('grupa', 'option')['pole']"
- "Osobna tabela wp_parking_price_history zamiast rozszerzania wp_price_history"
- "Cena m2 ukryta w widgecie na życzenie użytkownika (dane nadal w cronie/XML)"
- "Layout bez ramek, kolumnowy zamiast grid 2-kolumnowego"
patterns-established:
- "ACF group field access: get_field('group_name', 'option')['group_name_field']"
- "Parking popup reuse: fallback overlay usuwany jeśli apartamentowy istnieje"
duration: ~30min
completed: 2026-03-25
---
# Phase 3 Plan 01: Miejsca Postojowe Summary
**Widget Elementor wyswietlajacy ceny miejsc postojowych (zwykle/rodzinne) z historia cen, cron i XML export**
## Performance
| Metric | Value |
|--------|-------|
| Duration | ~30min |
| Completed | 2026-03-25 |
| Tasks | 2 auto + 2 checkpoints |
| Files modified | 4 (1 new, 3 modified) |
## Acceptance Criteria Results
| Criterion | Status | Notes |
|-----------|--------|-------|
| AC-1: Widget wyswietla ceny parkingowe | Pass | Dwa typy z cenami z ACF grup, layout kolumnowy |
| AC-2: Popup historia cen dziala | Pass | Reuse popup apartamentow, AJAX endpoint dziala |
| AC-3: Cron zapisuje ceny codziennie | Pass | INSERT IGNORE do wp_parking_price_history |
| AC-4: XML export zawiera miejsca postojowe | Pass | Sekcja <miejsca_postojowe> w /ceny-mieszkan.xml |
## Accomplishments
- Widget "Miejsca Postojowe" w Elementorze — 2 karty (zwykle/rodzinne) z ceną i przyciskiem historia cen
- Tabela wp_parking_price_history z codziennym zapisem cen przez WP Cron
- AJAX endpoint parking_get_price_history z popupem reusujacym overlay apartamentow
- XML /ceny-mieszkan.xml rozszerzony o sekcje <miejsca_postojowe> z historia
## Files Created/Modified
| File | Change | Purpose |
|------|--------|---------|
| `widgets/parking-spots.php` | Created | Elementor widget rendering parking spot cards |
| `elementor-addon.php` | Modified | DB table, cron extension, AJAX endpoint, XML export |
| `assets/js/main.js` | Modified | Parking price history click handler + AJAX |
| `assets/css/main.css` | Modified | Parking widget styles (no border, column layout) |
## Decisions Made
| Decision | Rationale | Impact |
|----------|-----------|--------|
| Osobna tabela wp_parking_price_history | Parking to opcje ACF, nie CPT — inna struktura (parking_type vs post_id) | Czysta separacja, brak zmian w istniejącej tabeli |
| ACF group access pattern | Pola cen są w grupach ACF, nie flat | Wymaga get_field('grupa', 'option')['pole'] |
| Ukrycie ceny m2 w widgecie | Request użytkownika — uproszczony wygląd | Dane m2 nadal w cronie i XML |
| Layout bez ramek, kolumnowy | Request użytkownika — bliższy designowi Figma | Prostszy CSS |
## Deviations from Plan
### Summary
| Type | Count | Impact |
|------|-------|--------|
| User-requested changes | 2 | Design adjustments, no functional impact |
| Auto-fixed | 1 | ACF group access pattern |
**Total impact:** Essential fixes + design preferences, no scope creep
### Details
1. **ACF group fields** — Plan zakladal flat access (get_field('pole', 'option')). Odkryto ze pola sa w grupach ACF. Naprawione na get_field('grupa', 'option')['pole'].
2. **Ukrycie ceny m2** — User request. Usunieto z HTML widgetu, dane nadal zapisywane.
3. **Layout bez ramek, kolumnowy** — User request. Zmieniono z grid 2-kolumnowego z ramkami na flex column bez ramek.
## Issues Encountered
| Issue | Resolution |
|-------|------------|
| Figma MCP niedostępny (oryginalny plik) | User udostępnił kopię, pobrano screenshot Frame 16 |
| Ceny nie wyświetlały się po wdrożeniu | ACF pola w grupach — naprawiony pattern dostępu |
## Next Phase Readiness
**Ready:**
- Milestone v0.2 Miejsca Postojowe kompletny (1 faza, 1 plan)
- Wszystkie AC spełnione
**Concerns:**
- WP Cron pseudocron — na produkcji zalecany systemowy cron
- Cena m2 ukryta — może wymagać przywrócenia w przyszłości
**Blockers:**
- None
---
*Phase: 03-miejsca-postojowe, Plan: 01*
*Completed: 2026-03-25*

53
.paul/verify_task1.php Normal file
View File

@@ -0,0 +1,53 @@
<?php
// Symulacja dbDelta — tworzymy tabelę bezpośrednio
$conn = new mysqli('host117523.hostido.net.pl', 'host117523_wyszynskiego12pagedevpl', 'yZs52KdErtTk9KmZ8XGq', 'host117523_wyszynskiego12pagedevpl');
if ($conn->connect_error) { die('Blad polaczenia: ' . $conn->connect_error); }
$conn->set_charset('utf8mb4');
$sql = "CREATE TABLE IF NOT EXISTS wp_price_history (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
post_id BIGINT UNSIGNED NOT NULL,
price VARCHAR(50) NOT NULL DEFAULT '',
price_m2 VARCHAR(50) NOT NULL DEFAULT '',
floor_space VARCHAR(50) NOT NULL DEFAULT '',
recorded_at DATE NOT NULL,
PRIMARY KEY (id),
UNIQUE KEY unique_daily (post_id, recorded_at),
KEY idx_post_id (post_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;";
if ($conn->query($sql)) {
echo "OK: Tabela wp_price_history utworzona lub juz istnieje.\n";
} else {
echo "BLAD: " . $conn->error . "\n";
}
// Sprawdz czy tabela istnieje
$r = $conn->query("SHOW TABLES LIKE 'wp_price_history'");
echo "Tabela w bazie: " . ($r->num_rows > 0 ? "TAK" : "NIE") . "\n";
// Opisz strukturę
$r2 = $conn->query("DESCRIBE wp_price_history");
echo "\nStruktura tabeli:\n";
while ($row = $r2->fetch_assoc()) {
echo " " . $row['Field'] . " | " . $row['Type'] . " | " . $row['Key'] . "\n";
}
// Test INSERT IGNORE z danymi apartamentu 203
$today = date('Y-m-d');
$conn->query("INSERT IGNORE INTO wp_price_history (post_id, price, price_m2, floor_space, recorded_at) VALUES (203, '677 920', '19 000', '35,68', '$today')");
echo "\nINSERT IGNORE dla apt 203 (dzisiaj): affected_rows=" . $conn->affected_rows . "\n";
// Powtorzenie — powinno byc 0 (IGNORE)
$conn->query("INSERT IGNORE INTO wp_price_history (post_id, price, price_m2, floor_space, recorded_at) VALUES (203, '677 920', '19 000', '35,68', '$today')");
echo "Powtorny INSERT IGNORE (powinno byc 0): affected_rows=" . $conn->affected_rows . "\n";
// Pokaz rekordy
$r3 = $conn->query("SELECT * FROM wp_price_history LIMIT 5");
echo "\nRekordy w tabeli:\n";
while ($row = $r3->fetch_assoc()) {
echo " ID=" . $row['id'] . " | post_id=" . $row['post_id'] . " | price=" . $row['price'] . " | date=" . $row['recorded_at'] . "\n";
}
$conn->close();