263 lines
14 KiB
Markdown
263 lines
14 KiB
Markdown
---
|
||
phase: 09-finalizacja
|
||
plan: 01
|
||
type: execute
|
||
wave: 1
|
||
depends_on: []
|
||
files_modified:
|
||
- wp-content/plugins/yacht-booking-system/frontend/assets/js/calendar.js
|
||
- wp-content/plugins/yacht-booking-system/frontend/assets/css/calendar.scss
|
||
- wp-content/plugins/yacht-booking-system/frontend/assets/css/calendar.css
|
||
- wp-content/plugins/yacht-booking-system/frontend/class-calendar-widget.php
|
||
autonomous: false
|
||
delegation: off
|
||
---
|
||
|
||
<objective>
|
||
## Goal
|
||
Wprowadzić wizualne oznaczenie „pół-dnia" na pierwszym i ostatnim dniu rezerwacji w kalendarzu frontowym (FullCalendar) oraz dostroić domyślną kolorystykę widgetu Elementor `yacht-calendar` do palety strony jachty3.pagedev.pl (granat + czerwony akcent).
|
||
|
||
## Purpose
|
||
Klient zgłosił, że obecna wizualizacja kalendarza nie odzwierciedla rzeczywistego rytmu wynajmu jachtów: jacht jest wydawany danego dnia od ustalonej godziny odbioru (po południu) i zwracany w dniu zakończenia rano. Pełne zablokowanie skrajnych dni rezerwacji wprowadza w błąd potencjalnych klientów — sugeruje, że dzień odbioru/zwrotu jest niedostępny, podczas gdy w praktyce można wtedy rozpocząć/zakończyć inną rezerwację. Dodatkowo obecna paleta zieleń+czerwień nie pasuje do granatowo-czerwonego brandingu strony.
|
||
|
||
## Output
|
||
- Zmodyfikowany kalendarz frontowy (JS + CSS) renderujący skos „pół-zajętego" dnia dla pierwszego i ostatniego dnia każdej ciągłej blokady (booking, GCal, iCal)
|
||
- Zaktualizowane domyślne kolory widgetu Elementor (`primary`, `available`, `booked`) dopasowane do palety strony
|
||
- Zachowana kompatybilność z istniejącymi instancjami widgetu (override przez ustawienia Elementora dalej działa)
|
||
</objective>
|
||
|
||
<context>
|
||
<clarifications>
|
||
- **Half-day** — Który dzień ma być wypełniony „w połowie"?
|
||
→ Odpowiedź: Pierwszy i ostatni dzień rezerwacji. Wizualnie: dzień startu = lewa połowa wolna, prawa połowa zajęta (odbiór po południu); dzień końca = lewa połowa zajęta, prawa połowa wolna (zwrot rano).
|
||
- **Kolorystyka** — Skąd brać kolory dopasowane do strony?
|
||
→ Odpowiedź: Zmienić domyślne wartości w `Calendar_Widget` (Elementor). Istniejące instancje będą mogły zachować swoje ustawienia (override) lub zresetować do nowych defaultów.
|
||
- **Blocked GCal** — Czy half-day dotyczy też blokad zewnętrznych (Google Calendar / iCal, bez `booking_id`)?
|
||
→ Odpowiedź: Tak — analogicznie. Pierwszy i ostatni dzień ciągłego pasma `blocked` także jest pół-zajęty. Detekcja na podstawie ciągłości statusu (poprzedni/następny dzień ma inny status lub inny `booking_id`).
|
||
- **Scope** — Czy to plan fazy 9 czy hotfix?
|
||
→ Odpowiedź: Plan 09-01 fazy 9 (UX/UI polish). Plany 09-02 (settings page), 09-03 (security audit), 09-04 (testy/tłumaczenia/dokumentacja) idą później.
|
||
- **Selectability ostatniego dnia** (wynika z odpowiedzi 1) — Czy pierwszy/ostatni dzień rezerwacji ma być klikalny dla nowej rezerwacji?
|
||
→ Odpowiedź: Wizualnie tak (skos pokazuje, że pół dnia jest wolne), natomiast logika walidacji rezerwacji **pozostaje bez zmian** w tym planie — overlap dalej blokuje wybór skrajnych dni. Zmiana logiki to osobna decyzja biznesowa (godziny check-in/out, polityka rezerwacji) i będzie tematem oddzielnego planu jeśli klient tego zechce.
|
||
</clarifications>
|
||
|
||
## Project Context
|
||
@.paul/PROJECT.md
|
||
@.paul/ROADMAP.md
|
||
@.paul/STATE.md
|
||
@.paul/codebase/architecture.md
|
||
|
||
## Source Files
|
||
@wp-content/plugins/yacht-booking-system/frontend/assets/js/calendar.js
|
||
@wp-content/plugins/yacht-booking-system/frontend/assets/css/calendar.scss
|
||
@wp-content/plugins/yacht-booking-system/frontend/class-calendar-widget.php
|
||
@wp-content/plugins/yacht-booking-system/includes/class-availability.php
|
||
</context>
|
||
|
||
<acceptance_criteria>
|
||
|
||
## AC-1: Skos na pierwszym dniu rezerwacji
|
||
```gherkin
|
||
Given jacht ma rezerwację w terminie 21–24 maja
|
||
When użytkownik otwiera kalendarz tego jachtu
|
||
Then dzień 21 maja renderuje się z lewą połową w kolorze "available" i prawą połową w kolorze "booked" (gradient po przekątnej z lewego dołu do prawej góry, lub liniowo 50/50)
|
||
And dni 22 i 23 maja są w pełni w kolorze "booked"
|
||
```
|
||
|
||
## AC-2: Skos na ostatnim dniu rezerwacji
|
||
```gherkin
|
||
Given jacht ma rezerwację w terminie 21–24 maja
|
||
When użytkownik otwiera kalendarz tego jachtu
|
||
Then dzień 24 maja renderuje się z lewą połową w kolorze "booked" i prawą połową w kolorze "available"
|
||
```
|
||
|
||
## AC-3: Detekcja ciągłości — różne booking_id obok siebie
|
||
```gherkin
|
||
Given jacht ma rezerwację A (15–18 maja, booking_id=10) i rezerwację B (19–22 maja, booking_id=11)
|
||
When kalendarz renderuje maj
|
||
Then dzień 18 jest "ostatni" rezerwacji A (skos prawy = available) — ale jeśli 19 jest pierwszym B, na styku 18/19 oba dni mają skosy w przeciwnych kierunkach
|
||
And dni 16, 17 (środek A) oraz 20, 21 (środek B) są w pełni booked
|
||
```
|
||
|
||
## AC-4: Skos także dla blokad GCal/iCal
|
||
```gherkin
|
||
Given jacht ma blokadę zewnętrzną (status=blocked, booking_id=null) w dniach 5–7 czerwca
|
||
When kalendarz renderuje czerwiec
|
||
Then dzień 5 czerwca = lewa połowa available, prawa booked
|
||
And dzień 7 czerwca = lewa booked, prawa available
|
||
And dzień 6 czerwca = w pełni booked
|
||
```
|
||
|
||
## AC-5: Nowa paleta domyślna widgetu
|
||
```gherkin
|
||
Given administrator dodaje świeży widget "Yacht Calendar" w Elementorze
|
||
When otwiera ustawienia stylu
|
||
Then domyślne kolory to: primary = granat strony (np. #0a2a5e), available = jasny / transparentny (np. #f5f9ff lub rgba), booked = czerwień strony (np. #d63638)
|
||
And istniejące widgety (z zapisanymi własnymi kolorami) zachowują swoje wartości — nie są nadpisywane
|
||
```
|
||
|
||
## AC-6: Walidacja wyboru dat niezmieniona
|
||
```gherkin
|
||
Given jacht ma rezerwację 21–24 maja
|
||
When użytkownik próbuje wybrać 24–26 maja w kalendarzu
|
||
Then system blokuje wybór (alert "Wybrane daty zawierają niedostępne terminy")
|
||
# Zmiana logiki check-in/check-out poza zakresem tego planu.
|
||
```
|
||
|
||
</acceptance_criteria>
|
||
|
||
<tasks>
|
||
|
||
<task type="auto">
|
||
<name>Task 1: Wzbogacić REST/JS o detekcję krawędzi rezerwacji i wyrenderować skos</name>
|
||
<files>
|
||
wp-content/plugins/yacht-booking-system/frontend/assets/js/calendar.js,
|
||
wp-content/plugins/yacht-booking-system/frontend/assets/css/calendar.scss,
|
||
wp-content/plugins/yacht-booking-system/frontend/assets/css/calendar.css
|
||
</files>
|
||
<action>
|
||
**Detekcja krawędzi (klient-side, w `events` callback):**
|
||
1. Po pobraniu danych z `/availability/{yacht_id}` posortować dni po dacie.
|
||
2. Dla każdego dnia o statusie != 'available' obliczyć:
|
||
- `isStart` = poprzedni dzień (date - 1) jest 'available' LUB ma inny `booking_id` LUB ma inny status (booked vs blocked).
|
||
- `isEnd` = następny dzień (date + 1) j.w.
|
||
- Jeżeli zarówno `isStart` jak i `isEnd` to dzień jest "single" (1-dniowa blokada) → traktuj jako pełen booked (nie skos), albo opcjonalnie skos w kształcie klepsydry — w tym planie: pełen booked dla 1-dniowych.
|
||
3. Zamiast pojedynczego eventu `display: 'background'` z jednym kolorem, dodaj `classNames`:
|
||
- `yacht-day-booked` (środek)
|
||
- `yacht-day-booked-start` (pierwszy dzień)
|
||
- `yacht-day-booked-end` (ostatni dzień)
|
||
- analogicznie `yacht-day-blocked-*` dla statusu 'blocked'
|
||
4. Zachować istniejący `backgroundColor` jako fallback dla starszych przeglądarek; rzeczywiste tło renderować przez CSS (linear-gradient).
|
||
5. Przekazać kolor `availableBg` i `bookedBg` do CSS przez CSS custom properties ustawiane na wrapperze: `--yacht-available-bg`, `--yacht-booked-bg`.
|
||
- Set `$wrapper.css({'--yacht-available-bg': availableBg, '--yacht-booked-bg': bookedBg})`.
|
||
|
||
**CSS (calendar.scss + skompilowany calendar.css):**
|
||
1. Dodaj reguły:
|
||
```css
|
||
.yacht-day-booked-start .fc-bg-event,
|
||
.yacht-day-booked-start.fc-day {
|
||
background: linear-gradient(to right,
|
||
var(--yacht-available-bg) 0%,
|
||
var(--yacht-available-bg) 50%,
|
||
var(--yacht-booked-bg) 50%,
|
||
var(--yacht-booked-bg) 100%) !important;
|
||
}
|
||
.yacht-day-booked-end .fc-bg-event,
|
||
.yacht-day-booked-end.fc-day {
|
||
background: linear-gradient(to right,
|
||
var(--yacht-booked-bg) 0%,
|
||
var(--yacht-booked-bg) 50%,
|
||
var(--yacht-available-bg) 50%,
|
||
var(--yacht-available-bg) 100%) !important;
|
||
}
|
||
/* Analogicznie dla blocked-* */
|
||
```
|
||
2. Skos liniowy 50/50 — preferowany nad ukośnym (`to bottom right`), bo zachowuje czytelność daty i nie nakłada się na cyfrę.
|
||
3. Zaktualizować legendę widgetu o trzeci stan "Częściowo zajęty" (gradient sample) — tylko jeśli widget już renderuje legendę; jeśli nie, pominąć.
|
||
|
||
**Nie zmieniać:**
|
||
- logiki walidacji `selectAllow` / `select` (AC-6).
|
||
- struktury REST API (`/availability/{yacht_id}` zwraca dalej te same pola).
|
||
|
||
**Avoid:**
|
||
- Mutacji `event.display` — zostaw `'background'`, klasy CSS wystarczą.
|
||
- Inline styles na komórkach (FullCalendar je nadpisuje na re-render).
|
||
</action>
|
||
<verify>
|
||
1. `php -l wp-content/plugins/yacht-booking-system/frontend/class-calendar-widget.php` — syntax OK.
|
||
2. Skompilować SCSS → CSS (lub edytować oba pliki ręcznie spójnie); `git diff calendar.css` pokazuje nowe selektory.
|
||
3. Manualnie: po deployu FTP otworzyć /rezerwacja-maja/, sprawdzić że dla istniejącej rezerwacji pierwszy/ostatni dzień ma skos. (CHECKPOINT human-verify w Task 3).
|
||
</verify>
|
||
<done>AC-1, AC-2, AC-3, AC-4, AC-6 spełnione.</done>
|
||
</task>
|
||
|
||
<task type="auto">
|
||
<name>Task 2: Zaktualizować domyślne kolory widgetu Elementor do palety strony</name>
|
||
<files>
|
||
wp-content/plugins/yacht-booking-system/frontend/class-calendar-widget.php
|
||
</files>
|
||
<action>
|
||
W `Calendar_Widget::register_controls()` (linie ~218–245 oraz ~272–274 dla `render()` i ~530–532 dla `_content_template()`) zmienić wartości `'default'` na paletę dopasowaną do strony jachty3.pagedev.pl:
|
||
|
||
- `primary_color`: `#2271b1` → `#0a2a5e` (granat główny strony)
|
||
- `available_color`: `#35b56a` → `#f5f9ff` (bardzo jasny niebieski / prawie biały)
|
||
- `booked_color`: `#e53935` → `#d63638` (czerwień akcentu strony, taka sama jak CTA)
|
||
|
||
Jeśli paleta strony zostanie później doprecyzowana — wartości można dostroić w ramach UNIFY. Punkt wyjścia: granat #0a2a5e + czerwień #d63638 (zgodne z screenshotem strony).
|
||
|
||
Dodatkowo:
|
||
- W szablonie legendy (linie ~566–570) zaktualizować `background-color` swatch'y do nowych defaultów (lub jeszcze lepiej: użyć CSS custom properties z wrappera, żeby legenda też reagowała na zmianę w Elementorze).
|
||
- Fallback w `calendar.js` (`normalizeColor`) — dodać stare zielone/czerwone `#35b56a` i `#e53935` jako "legacyColor", aby instancje wciąż używające tych wartości automatycznie dostały nowe domyślne. Dla istniejących instancji ze świadomie dobranymi kolorami (np. brand klienta) zachować jak jest — czyli **nie ruszać** instancji, gdzie wartość jest inna niż stary default.
|
||
|
||
**Avoid:**
|
||
- Migracji wartości w bazie danych (Elementor zapisuje per-widget; nie ruszamy istniejących).
|
||
- Łamania backward-compatibility dla widgetów bez ustawionego koloru (puste = nowy default).
|
||
</action>
|
||
<verify>
|
||
1. `php -l wp-content/plugins/yacht-booking-system/frontend/class-calendar-widget.php`.
|
||
2. Po deployu: dodać nowy widget Yacht Calendar w Elementor → sprawdzić że suwaki pokazują nowe wartości HEX.
|
||
3. Otworzyć stronę z istniejącym widgetem — kolory niezmienione (jeśli zapisane w meta) lub odświeżone (jeśli legacy zielony/czerwony).
|
||
</verify>
|
||
<done>AC-5 spełnione.</done>
|
||
</task>
|
||
|
||
<task type="checkpoint:human-verify" gate="blocking">
|
||
<what-built>
|
||
Wizualne oznaczenie pół-dni i nowa paleta widgetu na środowisku produkcyjnym (po deployu FTP).
|
||
</what-built>
|
||
<how-to-verify>
|
||
1. Po wgraniu plików przez ftp-kr odświeżyć z hard-reload: https://jachty3.pagedev.pl/rezerwacja-maja/
|
||
2. Wybrać miesiąc, w którym istnieje rezerwacja (lub stworzyć testową).
|
||
3. Sprawdzić wizualnie:
|
||
- Pierwszy dzień rezerwacji: lewa połowa jasna, prawa czerwona.
|
||
- Środkowe dni: w pełni czerwone.
|
||
- Ostatni dzień: lewa czerwona, prawa jasna.
|
||
- Tło wolnych dni: jasno-niebieskie / białe (dopasowane do strony).
|
||
- Brak regresji w wyborze dat (selecton działa, walidacja overlap aktywna).
|
||
4. Sprawdzić w Elementorze: nowy widget Yacht Calendar → defaultowe kolory = granat/jasny/czerwień.
|
||
5. Mobile (DevTools 375px) — skos czytelny, data nie znika.
|
||
</how-to-verify>
|
||
<resume-signal>Wpisz "approved" aby kontynuować, lub opisz problemy do poprawienia (kolor, kierunek skosu, kontrast itp.)</resume-signal>
|
||
</task>
|
||
|
||
</tasks>
|
||
|
||
<boundaries>
|
||
|
||
## DO NOT CHANGE
|
||
- `wp-content/plugins/yacht-booking-system/api/class-rest-controller.php` — REST API surface bez zmian.
|
||
- `wp-content/plugins/yacht-booking-system/includes/class-availability.php` — schemat danych i metody bez zmian.
|
||
- Logika walidacji rezerwacji w `Rest_Controller::create_booking()` i `selectAllow` w JS — nie zmieniać polityki overlap.
|
||
- `wp_yacht_availability` — schemat tabeli niezmieniony.
|
||
- Backend admin (`admin/class-admin.php` itd.) — plan dotyczy tylko frontendu.
|
||
- Istniejące zapisane ustawienia kolorów w meta widgetów Elementora.
|
||
|
||
## SCOPE LIMITS
|
||
- Tylko frontend kalendarza (FullCalendar w widgecie + shortcode).
|
||
- Tylko CSS + JS detekcja krawędzi; brak nowych endpointów REST.
|
||
- Bez zmian w polityce check-in/check-out (godziny odbioru/zwrotu jako konfiguracja → ewentualnie osobny plan).
|
||
- Bez zmian w systemie email / templates.
|
||
- Bez tłumaczeń .po/.mo (osobny plan 09-04).
|
||
|
||
</boundaries>
|
||
|
||
<verification>
|
||
- [ ] `php -l` na zmodyfikowanych plikach PHP — bez błędów składni.
|
||
- [ ] Skompilowany `calendar.css` zsynchronizowany z `calendar.scss`.
|
||
- [ ] Brak nowych warningów w konsoli przeglądarki (DevTools) na /rezerwacja-maja/.
|
||
- [ ] FullCalendar nadal renderuje miesiąc/dni i refetch działa po zmianie jachtu.
|
||
- [ ] Wszystkie AC (AC-1..AC-6) zweryfikowane wizualnie w checkpoint human-verify.
|
||
</verification>
|
||
|
||
<success_criteria>
|
||
- Skos na pierwszym/ostatnim dniu każdej ciągłej blokady (booked + blocked).
|
||
- Środkowe dni renderują się w pełnym kolorze booked.
|
||
- 1-dniowe blokady renderują się jako pełen booked (decyzja: nie używamy klepsydry).
|
||
- Nowe defaulty kolorów w widgecie pasują wizualnie do palety strony (granat + czerwień).
|
||
- Istniejące widgety z customowymi kolorami nie tracą swoich ustawień.
|
||
- Klient potwierdza ("approved") w checkpoint human-verify.
|
||
</success_criteria>
|
||
|
||
<output>
|
||
Po zakończeniu: `.paul/phases/09-finalizacja/09-01-SUMMARY.md`
|
||
</output>
|