**Zmiana 1: Wiersz "HISTORIA CEN"**
Znajdź wiersz z klasą `apartament-card__price-history` (linia ~157).
Zmień `| ` na:
```php
|
```
Reszta wiersza (tekst "HISTORIA CEN" + SVG) pozostaje bez zmian.
**Zmiana 2: Globalny popup HTML**
Dodaj PRZED `` (czyli po zamknięciu pętli while)
następujący HTML popupa (jeden egzemplarz dla całej strony):
```php
```
Unikaj: dodawania popup wewnątrz pętli while — tylko jeden egzemplarz na stronę.
Sprawdź PHP syntax: `php -l wp-content/plugins/elementor-addon/widgets/apartaments.php`
Sprawdź czy data-post-id jest w HTML widgetu przez DevTools lub view-source.
AC-1 spełnione: przycisk ma data-post-id; popup HTML istnieje w DOM
Task 2: CSS popup — main.scss i main.css
wp-content/plugins/elementor-addon/assets/css/main.scss,
wp-content/plugins/elementor-addon/assets/css/main.css
Dodaj na końcu pliku `main.scss` (po zamknięciu `.apartaments { }`) poniższe style.
Następnie dodaj **te same skompilowane style** (bez SCSS zagnieżdżeń, rozwinięte)
na końcu pliku `main.css`.
**Style do dodania w main.scss:**
```scss
// Historia cen — popup overlay
.price-history-overlay {
display: none;
position: fixed;
inset: 0;
z-index: 99999;
background: rgba(25, 44, 68, 0.55);
align-items: center;
justify-content: center;
padding: 20px;
&.is-open {
display: flex;
}
}
.price-history-modal {
position: relative;
background: #fff;
border: 4px solid #192c44;
padding: 32px 36px 28px;
max-width: 560px;
width: 100%;
max-height: 80vh;
overflow-y: auto;
font-family: 'Barlow', sans-serif;
color: #192c44;
@media (max-width: 600px) {
padding: 24px 20px 20px;
}
&__close {
position: absolute;
top: 14px;
right: 14px;
background: none;
border: 2px solid #192c44;
width: 30px;
height: 30px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
padding: 0;
line-height: 1;
}
&__title {
font-size: 22px;
font-weight: 700;
margin: 0 0 18px;
padding-right: 40px;
color: #192c44;
}
&__current {
margin-bottom: 16px;
}
&__row {
display: flex;
justify-content: space-between;
font-size: 18px;
line-height: 1.5;
color: #192c44;
&--bold {
font-weight: 700;
}
}
&__val {
text-align: right;
}
&__table-wrap {
border-top: 1px solid #192c44;
padding-top: 12px;
margin-top: 4px;
}
&__table {
width: 100%;
border-collapse: collapse;
tr {
border: none;
background: transparent;
td {
padding: 4px 0;
font-size: 15px;
color: #192c44;
font-family: 'Barlow', sans-serif;
font-weight: 400;
border: none;
background: transparent;
&:last-child {
text-align: right;
}
&:nth-child(2) {
text-align: center;
}
}
}
}
}
```
**Skompilowana wersja CSS do dodania na końcu main.css** (rozwinięte selektory, bez &):
```css
/* Historia cen — popup */
.price-history-overlay {
display: none;
position: fixed;
inset: 0;
z-index: 99999;
background: rgba(25, 44, 68, 0.55);
align-items: center;
justify-content: center;
padding: 20px;
}
.price-history-overlay.is-open {
display: flex;
}
.price-history-modal {
position: relative;
background: #fff;
border: 4px solid #192c44;
padding: 32px 36px 28px;
max-width: 560px;
width: 100%;
max-height: 80vh;
overflow-y: auto;
font-family: 'Barlow', sans-serif;
color: #192c44;
}
@media (max-width: 600px) {
.price-history-modal {
padding: 24px 20px 20px;
}
}
.price-history-modal__close {
position: absolute;
top: 14px;
right: 14px;
background: none;
border: 2px solid #192c44;
width: 30px;
height: 30px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
padding: 0;
line-height: 1;
}
.price-history-modal__title {
font-size: 22px;
font-weight: 700;
margin: 0 0 18px;
padding-right: 40px;
color: #192c44;
}
.price-history-modal__current {
margin-bottom: 16px;
}
.price-history-modal__row {
display: flex;
justify-content: space-between;
font-size: 18px;
line-height: 1.5;
color: #192c44;
}
.price-history-modal__row--bold {
font-weight: 700;
}
.price-history-modal__val {
text-align: right;
}
.price-history-modal__table-wrap {
border-top: 1px solid #192c44;
padding-top: 12px;
margin-top: 4px;
}
.price-history-modal__table {
width: 100%;
border-collapse: collapse;
}
.price-history-modal__table tr {
border: none;
background: transparent;
}
.price-history-modal__table td {
padding: 4px 0;
font-size: 15px;
color: #192c44;
font-family: 'Barlow', sans-serif;
font-weight: 400;
border: none;
background: transparent;
}
.price-history-modal__table td:last-child {
text-align: right;
}
.price-history-modal__table td:nth-child(2) {
text-align: center;
}
```
Unikaj: modyfikowania istniejących reguł CSS — tylko append na końcu.
Unikaj: zmian w mapie .css.map — pozostaw jak jest.
Sprawdź że klasy `.price-history-overlay` i `.price-history-modal` są obecne w main.css.
Sprawdź że nie ma błędów składni SCSS (ręczna inspekcja nawiasów).
AC-2, AC-3 (style): modal wygląda zgodnie z projektem
Task 3: JS — obsługa kliknięcia, AJAX, render popupa
wp-content/plugins/elementor-addon/assets/js/main.js
Dodaj na końcu pliku `main.js` (po zamknięciu istniejącego DOMContentLoaded)
nowy blok obsługi historii cen.
**Kod do dodania:**
```javascript
// Historia cen
document.addEventListener('DOMContentLoaded', function () {
var overlay = document.getElementById('price-history-overlay');
var closeBtn = document.getElementById('price-history-close');
if (!overlay) return; // popup nie istnieje na tej stronie
function openPopup() {
overlay.setAttribute('aria-hidden', 'false');
overlay.classList.add('is-open');
document.body.style.overflow = 'hidden';
}
function closePopup() {
overlay.setAttribute('aria-hidden', 'true');
overlay.classList.remove('is-open');
document.body.style.overflow = '';
}
// Zamknij przyciskiem X
closeBtn.addEventListener('click', closePopup);
// Zamknij klikając na overlay (poza modalem)
overlay.addEventListener('click', function (e) {
if (e.target === overlay) closePopup();
});
// Zamknij klawiszem Escape
document.addEventListener('keydown', function (e) {
if (e.key === 'Escape' && overlay.classList.contains('is-open')) closePopup();
});
// Kliknięcie w przycisk Historia cen
document.querySelectorAll('.btn-historia-cen').forEach(function (btn) {
btn.addEventListener('click', function () {
var postId = this.dataset.postId;
if (!postId) return;
// Reset i pokaż "Ładowanie..."
document.getElementById('price-history-title').textContent = 'Ładowanie...';
document.getElementById('price-history-price').textContent = '';
document.getElementById('price-history-price-m2').textContent = '';
document.getElementById('price-history-tbody').innerHTML = '';
openPopup();
// Sprawdź dostępność danych globalnych (wp_localize_script)
if (typeof apartamentsData === 'undefined') {
document.getElementById('price-history-title').textContent = 'Błąd konfiguracji';
return;
}
// Buduj FormData
var formData = new FormData();
formData.append('action', 'apartamenty_get_price_history');
formData.append('post_id', postId);
formData.append('nonce', apartamentsData.nonce);
fetch(apartamentsData.ajaxUrl, {
method: 'POST',
body: formData,
credentials: 'same-origin',
})
.then(function (res) { return res.json(); })
.then(function (json) {
if (!json.success) {
document.getElementById('price-history-title').textContent = 'Brak danych';
return;
}
var d = json.data;
document.getElementById('price-history-title').textContent =
d.title || '';
document.getElementById('price-history-price').textContent =
d.price ? d.price + ' zł' : '—';
document.getElementById('price-history-price-m2').textContent =
d.price_m2 ? d.price_m2 + ' zł' : '—';
var tbody = document.getElementById('price-history-tbody');
if (!d.history || d.history.length === 0) {
tbody.innerHTML = '| Brak historii cen | ';
return;
}
tbody.innerHTML = d.history.map(function (row) {
return '' +
'| ' + (row.recorded_at || '') + ' | ' +
'' + (row.price_m2 ? row.price_m2 + ' zł/m²' : '—') + ' | ' +
'' + (row.price ? row.price + ' zł' : '—') + ' | ' +
' ';
}).join('');
})
.catch(function () {
document.getElementById('price-history-title').textContent = 'Błąd ładowania';
});
});
});
});
```
Unikaj: modyfikowania istniejącego bloku DOMContentLoaded (Swiper/Fancybox) — tylko append.
Unikaj: jQuery — używaj vanilla JS zgodnie z istniejącym stylem kodu.
`php -l` nie jest tu potrzebny — sprawdź składnię JS ręcznie (nawiasy, cudzysłowy).
Po wgraniu: otwórz stronę /apartamenty/, otwórz DevTools Console,
kliknij "HISTORIA CEN" → popup powinien się pojawić z danymi lub "Ładowanie...".
AC-2, AC-3, AC-4, AC-5 spełnione: popup otwiera się z danymi AJAX, zamyka się poprawnie
Popup „Historia cen" — kliknięcie przycisku otwiera modal z danymi z AJAX.
Przycisk ma data-post-id, popup zamyka się przez X / klik overlay / Escape.
1. Odwiedź: https://wyszynskiego12.pagedev.pl/apartamenty/
2. Odszukaj wiersz „HISTORIA CEN" przy dowolnym apartamencie i kliknij go
3. Sprawdź czy pojawia się modal z:
- Tytułem apartamentu (np. „Apartament 15")
- Ceną brutto (bold)
- Ceną m² (normal)
- Tabelą historii (lub „Brak historii cen" jeśli tabela pusta)
4. Kliknij X → popup zamknięty
5. Kliknij poza modalem → popup zamknięty
6. Naciśnij Escape → popup zamknięty
7. Otwórz DevTools → Console → brak błędów JavaScript
Wpisz "zatwierdzone" lub opisz problemy do poprawienia
## DO NOT CHANGE
- wp-content/plugins/elementor-addon/elementor-addon.php (ukończony w planie 01-01)
- wp-content/plugins/elementor-addon/plugins/ (biblioteki zewnętrzne)
- wp-config.php
## SCOPE LIMITS
- Nie dodawaj animacji CSS poza prostym display:flex/none
- Nie dodawaj nowych zależności JS (bez jQuery, bez bibliotek)
- Popup ma jeden egzemplarz na stronę — nie w pętli
- Nie modyfikuj istniejących reguł CSS — tylko append
Before declaring plan complete:
- [ ] PHP syntax OK: `php -l widgets/apartaments.php`
- [ ] Klasa `.price-history-overlay` istnieje w main.css
- [ ] Klasa `.btn-historia-cen` jest na wierszu HISTORIA CEN w HTML
- [ ] `data-post-id` jest ustawiony poprawnie dla każdego apartamentu
- [ ] JS nie wyrzuca błędów w konsoli
- [ ] Checkpoint human-verify zatwierdzony
- Kliknięcie "HISTORIA CEN" otwiera popup z danymi apartamentu
- Popup zamyka się przez X, klik overlay i Escape
- Stan ładowania i błędu jest obsługiwany
- Brak błędów JS w konsoli
- Wygląd zgodny z projektem (font Barlow, kolor #192c44, border 4px)
|