update
This commit is contained in:
329
.paul/phases/09-finalizacja/09-04-PLAN.md
Normal file
329
.paul/phases/09-finalizacja/09-04-PLAN.md
Normal file
@@ -0,0 +1,329 @@
|
||||
---
|
||||
phase: 09-finalizacja
|
||||
plan: 04
|
||||
type: execute
|
||||
wave: 1
|
||||
depends_on: []
|
||||
files_modified:
|
||||
- wp-content/plugins/yacht-booking-system/includes/class-settings.php
|
||||
- wp-content/plugins/yacht-booking-system/includes/class-installer.php
|
||||
- wp-content/plugins/yacht-booking-system/admin/class-admin.php
|
||||
- wp-content/plugins/yacht-booking-system/admin/views/settings-page.php
|
||||
- wp-content/plugins/yacht-booking-system/integrations/ical/class-ical-import.php
|
||||
- wp-content/plugins/yacht-booking-system/api/class-rest-controller.php
|
||||
- wp-content/plugins/yacht-booking-system/includes/class-yacht-booking.php
|
||||
- wp-content/plugins/yacht-booking-system/frontend/class-calendar-widget-all.php (NEW)
|
||||
- wp-content/plugins/yacht-booking-system/frontend/class-shortcode.php
|
||||
- wp-content/plugins/yacht-booking-system/assets/js/calendar-all.js (NEW)
|
||||
- wp-content/plugins/yacht-booking-system/assets/css/calendar-all.css (NEW)
|
||||
autonomous: false
|
||||
delegation: off
|
||||
---
|
||||
|
||||
<objective>
|
||||
## Goal
|
||||
Wprowadzić tryb "globalnej" synchronizacji iCal (wszystkie eventy z jednego feedu trafiają do wspólnego storage bez per-yacht matchingu) oraz nowy publiczny widget kalendarza pokazujący zajętość WSZYSTKICH publikowanych jachtów na jednej siatce, z kolorami per-jacht i wizualnym efektem "half-day" na pierwszym/ostatnim dniu rezerwacji.
|
||||
|
||||
## Purpose
|
||||
- Klient prowadzi jeden wspólny Google Calendar do wszystkich jachtów. Obecny tryb wymaga prefiksu w SUMMARY ("Maja - Klient") i wyrzuca nierozpoznane eventy. Nowy tryb pozwala importować je wszystkie bez utraty (np. "Pierwszy dzień szkoły") jako wydarzenia informacyjne na wspólnym widoku.
|
||||
- Frontend ma jedno miejsce ("kalendarz floty") gdzie potencjalny klient widzi wszystkie zajętości naraz, bez rozpraszającego efektu ukośników z trybu per-jacht. Half-day daje wizualny sygnał, że ktoś może wynająć od/do południa.
|
||||
|
||||
## Output
|
||||
- Settings: nowy select `ical_sync_mode` (`per_yacht` | `global`)
|
||||
- iCal Import: gałąź `global` zapisuje WSZYSTKIE eventy do wspólnego storage (`_booking_source = 'ical_global_calendar'`, brak yacht_id), bez wpisów do `wp_yacht_availability`
|
||||
- REST: `GET /availability/all` — zwraca eventy FullCalendar dla wszystkich jachtów + globalne wydarzenia, z kolorami auto-paleta i czasami timed (12:00 → 12:00)
|
||||
- Nowy widget Elementor `Yacht_Calendar_All_Widget` + shortcode `[yacht_calendar_all]` renderujący FullCalendar timed-grid z legendą jachtów
|
||||
</objective>
|
||||
|
||||
<context>
|
||||
<clarifications>
|
||||
- **Unmatched** — Co zrobić z eventami iCal bez prefiksu lub z nieznaną nazwą jachtu?
|
||||
→ Odpowiedź: Dodatkowa opcja w ustawieniach przełączająca tryb sync. Tryb `per_yacht` (obecny — match po prefiksie) lub `global` (jeden wspólny kalendarz, wszystkie eventy zapisywane bez przypisywania do jachtów; w danym dniu może być kilka wydarzeń).
|
||||
- **Widget zakres** — Nowy widget pokazuje które jachty?
|
||||
→ Odpowiedź: Wszystkie publikowane jachty (auto, `post_status = publish`).
|
||||
- **Rozróżnienie** — Jak odróżnić rezerwacje różnych jachtów?
|
||||
→ Odpowiedź: Kolor per jacht z auto palety (predefiniowana tablica kolorów indeksowana wg kolejności yacht_id, deterministycznie).
|
||||
- **Half-day** — Jak pokazać start/koniec w połowie dnia?
|
||||
→ Odpowiedź: FullCalendar timed events. Dane all-day konwertowane na timed (start = data 12:00, end = data+1 12:00) na poziomie REST endpointu.
|
||||
</clarifications>
|
||||
|
||||
## Project Context
|
||||
@.paul/PROJECT.md
|
||||
@.paul/ROADMAP.md
|
||||
@.paul/STATE.md
|
||||
@.paul/codebase/architecture.md
|
||||
@.paul/codebase/db_schema.md
|
||||
|
||||
## Prior Work
|
||||
@.paul/phases/09-finalizacja/09-02-SUMMARY.md
|
||||
@.paul/phases/09-finalizacja/09-03-SUMMARY.md
|
||||
|
||||
## Source Files
|
||||
@wp-content/plugins/yacht-booking-system/integrations/ical/class-ical-import.php
|
||||
@wp-content/plugins/yacht-booking-system/includes/class-settings.php
|
||||
@wp-content/plugins/yacht-booking-system/admin/class-admin.php
|
||||
@wp-content/plugins/yacht-booking-system/admin/views/settings-page.php
|
||||
@wp-content/plugins/yacht-booking-system/api/class-rest-controller.php
|
||||
@wp-content/plugins/yacht-booking-system/frontend/class-calendar-widget.php
|
||||
@wp-content/plugins/yacht-booking-system/frontend/class-shortcode.php
|
||||
@wp-content/plugins/yacht-booking-system/includes/class-yacht-booking.php
|
||||
@wp-content/plugins/yacht-booking-system/includes/class-installer.php
|
||||
</context>
|
||||
|
||||
<acceptance_criteria>
|
||||
|
||||
## AC-1: Settings — przełącznik trybu synchronizacji iCal
|
||||
```gherkin
|
||||
Given admin otwiera "Yacht Booking → Settings → Synchronizacja"
|
||||
When zobaczy nowe pole "Tryb synchronizacji iCal" z opcjami "Per jacht" i "Wspólny kalendarz"
|
||||
And wybiera "Wspólny kalendarz" i zapisuje
|
||||
Then opcja `yacht_booking_ical_sync_mode` w wp_options = "global"
|
||||
And formularz pokazuje wybraną wartość po reload
|
||||
And opis pomocniczy wyjaśnia różnicę między trybami (per_yacht: matching po prefiksie / global: wszystkie eventy bez filtrowania)
|
||||
```
|
||||
|
||||
## AC-2: Import iCal w trybie globalnym — wszystkie eventy bez filtrowania
|
||||
```gherkin
|
||||
Given `yacht_booking_ical_sync_mode = "global"` i feed URL ustawiony
|
||||
And feed zawiera 32 eventy (z prefiksami "Kubuś -", "Maja -", bez prefiksu "Pierwszy dzień szkoły", bez SUMMARY itp.)
|
||||
When uruchamia się hook `yacht_booking_ical_global_import`
|
||||
Then powstaje booking dla KAŻDEGO eventu z UID i `start`/`end` (poza past events)
|
||||
And `_booking_source = "ical_global_calendar"`, `_booking_yacht_id = 0`, `_booking_status = "confirmed"`
|
||||
And eventy NIE są wpisywane do `wp_yacht_availability` (nie blokują dostępności żadnego jachtu)
|
||||
And eventy bez SUMMARY otrzymują domyślny tytuł (np. "Wydarzenie kalendarza")
|
||||
And ponowne uruchomienie cron-u (idempotencja) — bookingi z tymi samymi UID są aktualizowane, nie duplikowane
|
||||
And eventy obecne w DB ale brakujące w nowym feedzie są usuwane (stale cleanup)
|
||||
```
|
||||
|
||||
## AC-3: Import iCal w trybie per-jacht — bez regresji
|
||||
```gherkin
|
||||
Given `yacht_booking_ical_sync_mode = "per_yacht"` (domyślne dla istniejących instalacji)
|
||||
When uruchamia się hook globalnego importu
|
||||
Then zachowanie jest IDENTYCZNE jak przed tą zmianą (matching po prefiksie SUMMARY, wpisy do `wp_yacht_availability`, stale cleanup ograniczony do `_booking_source = "ical_import_global"`)
|
||||
And istniejące bookingi importowane wcześniej w trybie per-jacht działają dalej i są nadal aktualizowane
|
||||
```
|
||||
|
||||
## AC-4: REST endpoint `GET /availability/all`
|
||||
```gherkin
|
||||
Given istnieje min. 2 publikowane jachty (np. "Kubuś", "Maja") z rezerwacjami
|
||||
And w trybie globalnym istnieją wydarzenia z `_booking_source = "ical_global_calendar"`
|
||||
When klient niezalogowany wywołuje `GET /wp-json/yacht-booking/v1/availability/all?start=2026-05-01&end=2026-12-31`
|
||||
Then odpowiedź to JSON tablica obiektów FullCalendar event:
|
||||
{ id, title, start (ISO datetime z "T12:00:00"), end (ISO datetime z "T12:00:00"), color, yacht_id }
|
||||
And bookingi per-jacht mają `color` z deterministycznej palety (tablica 8 kolorów indeksowana wg kolejności yacht_id)
|
||||
And globalne wydarzenia mają osobny kolor (np. szary `#7f8c8d`) i `yacht_id = 0`
|
||||
And tylko bookingi `confirmed`/`pending` są zwracane (nie `cancelled`/`rejected`)
|
||||
And `start <= end` zachowane
|
||||
```
|
||||
|
||||
## AC-5: Nowy widget i shortcode
|
||||
```gherkin
|
||||
Given strona z `[yacht_calendar_all]` lub widgetem Elementor "Yacht Calendar (wszystkie jachty)"
|
||||
When klient otwiera stronę
|
||||
Then widoczny FullCalendar w widoku miesięcznym (dayGridMonth)
|
||||
And eventy z `GET /availability/all` są renderowane jako timed events 12:00 → 12:00 (efekt half-day na pierwszym/ostatnim dniu rezerwacji)
|
||||
And nad/pod kalendarzem jest legenda kolorów (kropka + nazwa jachtu) auto-generowana z palety
|
||||
And widget jest read-only (brak formularza rezerwacji, brak klikalności dnia)
|
||||
And brak ukośników (cell background pełny / pusty)
|
||||
```
|
||||
|
||||
## AC-6: Auto paleta kolorów per jacht
|
||||
```gherkin
|
||||
Given lista jachtów posortowana po ID rosnąco
|
||||
When system mapuje yacht_id → kolor
|
||||
Then używana jest stała tablica min. 8 kolorów (np. #3498db, #e74c3c, #2ecc71, #f39c12, #9b59b6, #1abc9c, #34495e, #d35400)
|
||||
And mapowanie jest deterministyczne (yacht_id → index modulo długość palety) — ten sam yacht zawsze ten sam kolor
|
||||
And paleta jest wspólna dla REST endpointu i frontendowej legendy
|
||||
```
|
||||
|
||||
</acceptance_criteria>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Settings — przełącznik trybu sync iCal + zachowanie per_yacht jako default</name>
|
||||
<files>
|
||||
wp-content/plugins/yacht-booking-system/includes/class-settings.php,
|
||||
wp-content/plugins/yacht-booking-system/includes/class-installer.php,
|
||||
wp-content/plugins/yacht-booking-system/admin/class-admin.php,
|
||||
wp-content/plugins/yacht-booking-system/admin/views/settings-page.php
|
||||
</files>
|
||||
<action>
|
||||
1. `Settings`: dodaj typowany getter `get_ical_sync_mode()` zwracający `'per_yacht'` lub `'global'` (default: `'per_yacht'`). Klucz opcji: `yacht_booking_ical_sync_mode`. Dodaj setter w obecnym wzorcu klasy.
|
||||
2. `Installer`: dopisz default opcji `yacht_booking_ical_sync_mode = 'per_yacht'` do tablicy defaultów (nie nadpisuj istniejącej wartości jeśli jest).
|
||||
3. `Admin::process_settings_save()`: obsłuż nowe pole formularza (sanitize_text_field + whitelista wartości; nieznane → fallback `per_yacht`).
|
||||
4. `settings-page.php` (sekcja "Synchronizacja"): dodaj `<select name="ical_sync_mode">` z dwoma opcjami i opisem pomocniczym po polsku wyjaśniającym różnicę. Selected = bieżąca wartość. Zachowaj wzorzec nonce + i18n istniejący w pliku.
|
||||
Avoid: dodawanie nowej tabeli/migration — wystarczy `wp_options`. Avoid: zmiana default na `global` (regresja dla istniejących klientów).
|
||||
</action>
|
||||
<verify>
|
||||
- W WP Admin → Settings widzę nowe pole, mogę zapisać "Wspólny kalendarz" i po reload jest zaznaczone.
|
||||
- `wp option get yacht_booking_ical_sync_mode` zwraca `global`.
|
||||
- `php -l` na każdym zmienionym pliku.
|
||||
</verify>
|
||||
<done>AC-1 satisfied.</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: ICal_Import — gałąź global (storage bez per-yacht matchingu, idempotencja, stale cleanup)</name>
|
||||
<files>
|
||||
wp-content/plugins/yacht-booking-system/integrations/ical/class-ical-import.php
|
||||
</files>
|
||||
<action>
|
||||
1. W `run_global_import()` po pobraniu i sparsowaniu eventów odczytaj `Settings::get_ical_sync_mode()`.
|
||||
2. Jeśli `per_yacht` — kod bez zmian (obecna ścieżka match po prefiksie + wpisy do availability).
|
||||
3. Jeśli `global` — pomiń `build_yacht_lookup_map()` / `match_yacht_by_prefix()`. Dla KAŻDEGO eventu (z UID + start + end, pomijając past events) wywołaj nową metodę `upsert_global_calendar_event($event, $existing_id)`:
|
||||
- Wstawia/aktualizuje CPT `yacht_booking` z metami: `_booking_source = 'ical_global_calendar'`, `_booking_yacht_id = 0`, `_booking_status = 'confirmed'`, `_ical_event_uid = uid`, `_booking_start_date`, `_booking_end_date`, `_booking_customer_name = 'Google Calendar (kalendarz wspólny)'`, `_booking_total_price = 0`, `_booking_notes = summary`.
|
||||
- Tytuł postu: `summary` lub fallback `__( 'Wydarzenie kalendarza', 'yacht-booking' )` gdy puste.
|
||||
- NIE wywołuj `Availability::mark_as_booked()` (wydarzenia globalne nie blokują dostępności jachtów).
|
||||
4. Stale cleanup: w trybie global pobierz mapę istniejących bookingów po `_booking_source = 'ical_global_calendar'` (nowa stała `GLOBAL_CALENDAR_SOURCE`) i usuń te których UID brakuje w nowym feedzie (`wp_delete_post`, force).
|
||||
5. Stale cleanup w trybie per_yacht musi pozostać ograniczony do `_booking_source = 'ical_import_global'` (obecna stała) — nie tykać bookingów `ical_global_calendar` w drugą stronę i odwrotnie. Dwie stałe, dwie ścieżki cleanup.
|
||||
6. Logowanie: w trybie global loguj liczbę zaimportowanych / zaktualizowanych / usuniętych eventów.
|
||||
Avoid: dotykanie `wp_yacht_availability` w trybie global. Avoid: zmiana sygnatury `run_global_import()` (cron callback).
|
||||
</action>
|
||||
<verify>
|
||||
- Test ręczny: ustaw URL na lokalną kopię `D:\temp\basic.ics` (zhostowaną w WP uploads lub serve), włącz tryb `global`, uruchom `wp cron event run yacht_booking_ical_global_import`.
|
||||
- W WP Admin → Bookings widzę ~30 nowych pozycji z prefiksem "GCal:" lub tytułem eventu, brak wpływu na dostępność `yacht`.
|
||||
- Drugie uruchomienie cron-u nie tworzy duplikatów (count się zgadza).
|
||||
- `wp db query "SELECT COUNT(*) FROM wp_yacht_availability WHERE booking_id IN (SELECT post_id FROM wp_postmeta WHERE meta_key='_booking_source' AND meta_value='ical_global_calendar')"` zwraca 0.
|
||||
- Przełącz na `per_yacht` i uruchom — nowa logika nie ma efektu, stara działa jak wcześniej.
|
||||
- `php -l`.
|
||||
</verify>
|
||||
<done>AC-2 + AC-3 satisfied.</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 3: REST endpoint /availability/all — agregacja wszystkich jachtów + globalnych eventów z kolorami i timed</name>
|
||||
<files>
|
||||
wp-content/plugins/yacht-booking-system/api/class-rest-controller.php,
|
||||
wp-content/plugins/yacht-booking-system/includes/class-yacht-booking.php
|
||||
</files>
|
||||
<action>
|
||||
1. W `Rest_Controller`: dodaj nową metodę `get_all_availability( $request )` zarejestrowaną jako `GET /yacht-booking/v1/availability/all` (callback w `register_rest_routes()`, `permission_callback => '__return_true'`).
|
||||
2. Walidacja parametrów `start`, `end` (Y-m-d, opcjonalne — default: pierwszy dzień bieżącego miesiąca / + 12 mies.).
|
||||
3. Pobierz publikowane jachty (`get_posts` post_type=yacht). Zbuduj mapę `yacht_id => color` przez nową statyczną metodę `Rest_Controller::get_yacht_color_palette( array $yacht_ids )`:
|
||||
- Stała tablica 8 kolorów hex.
|
||||
- Mapuj `yacht_id` (sortowane rosnąco) na `palette[ index % count(palette) ]`.
|
||||
- Stała kolor globalnego eventu: `#7f8c8d`.
|
||||
4. Query bookings: `post_type = yacht_booking`, status `confirmed` lub `pending`, daty przecinające `start`–`end`. Per booking zwróć:
|
||||
```
|
||||
{
|
||||
id: booking_id,
|
||||
title: '<nazwa_jachtu> — <imię_klienta>' lub tytuł postu dla global,
|
||||
start: '<start_date>T12:00:00',
|
||||
end: '<end_date>T12:00:00',
|
||||
color: <z palety lub szary dla global>,
|
||||
yacht_id: <id lub 0>
|
||||
}
|
||||
```
|
||||
5. Globalne eventy (`_booking_source = ical_global_calendar`) traktowane jednolicie z yacht_id=0 i kolorem szarym; tytuł = `_booking_notes` lub post_title.
|
||||
6. Pomiń `cancelled`/`rejected`.
|
||||
7. W `Yacht_Booking::register_rest_routes()` upewnij się, że nowa trasa się rejestruje (jeśli rejestracja jest delegowana do `Rest_Controller::register_routes()` — bez zmiany).
|
||||
Avoid: cache na poziomie endpointu (małe wolumeny, prosto). Avoid: dodawanie nowych zależności / SDK.
|
||||
</action>
|
||||
<verify>
|
||||
- `curl 'https://<host>/wp-json/yacht-booking/v1/availability/all?start=2026-05-01&end=2026-12-31'` zwraca tablicę JSON z polami { id, title, start, end, color, yacht_id }.
|
||||
- Każdy yacht_id ma stały kolor między requestami.
|
||||
- Bookingi per-yacht mają yacht_id != 0; globalne mają yacht_id = 0 i kolor `#7f8c8d`.
|
||||
- Daty zawierają `T12:00:00`.
|
||||
- `php -l`.
|
||||
</verify>
|
||||
<done>AC-4 + AC-6 satisfied.</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 4: Widget Elementor + shortcode "yacht_calendar_all" + JS/CSS</name>
|
||||
<files>
|
||||
wp-content/plugins/yacht-booking-system/frontend/class-calendar-widget-all.php (NEW),
|
||||
wp-content/plugins/yacht-booking-system/frontend/class-shortcode.php,
|
||||
wp-content/plugins/yacht-booking-system/assets/js/calendar-all.js (NEW),
|
||||
wp-content/plugins/yacht-booking-system/assets/css/calendar-all.css (NEW),
|
||||
wp-content/plugins/yacht-booking-system/includes/class-yacht-booking.php
|
||||
</files>
|
||||
<action>
|
||||
1. **Nowy widget** `Yacht_Calendar_All_Widget` (extends `\Elementor\Widget_Base`) — wzorowany na `Calendar_Widget`, name=`yacht-calendar-all`, title=`Yacht Calendar (wszystkie jachty)`, ikona kalendarza. `render()` wypisuje `<div class="yacht-calendar-all" data-rest="<URL>"></div>`.
|
||||
2. **Shortcode** `[yacht_calendar_all]` w `Shortcode` (lub nowa metoda) — bez atrybutów. Wypisuje ten sam markup co widget.
|
||||
3. **`Yacht_Booking`**: rejestracja widgetu w `register_elementor_widgets()` (dopisz obok istniejącego). Conditional enqueue assets `calendar-all.js`/`calendar-all.css` gdy w treści jest shortcode lub na stronie z widgetem (rozszerz obecny mechanizm).
|
||||
4. **`calendar-all.js`** (IIFE jQuery): inicjalizacja FullCalendar v6 (CDN), `initialView: 'dayGridMonth'`, `events: <URL z data-rest>`, `displayEventTime: false`, `eventDisplay: 'block'`. Po `eventDidMount` dodaj klasę `.is-half-day-start` / `.is-half-day-end` do pierwszej/ostatniej komórki eventu (na podstawie hours = 12). Renderuj legendę (lista jachtów + kolorów) pobraną z dodatkowego endpointu `GET /availability/all/legend` LUB wyciągniętą z eventów po pierwszym fetch (wybierz prostsze — preferuj wyciąganie z eventów na froncie).
|
||||
5. **`calendar-all.css`** — minimalistyczny styl: ukryj kropkę przy timed event, pełne wypełnienie kafelka kolorem eventu, half-day cell renderowany przez gradient `linear-gradient(to right, transparent 50%, var(--color) 50%)` na pierwszym dniu i odwrotnie na ostatnim. Brak ukośników. Mobile-first.
|
||||
6. Brak modal-a / formularza rezerwacji — read-only.
|
||||
Avoid: npm/bundler — FullCalendar via CDN jak istniejący widget. Avoid: dotykanie istniejącego widgetu/CSS.
|
||||
</action>
|
||||
<verify>
|
||||
- `php -l` na nowych/zmienionych plikach PHP.
|
||||
- Strona z `[yacht_calendar_all]` renderuje kalendarz z eventami pobranymi z REST.
|
||||
- Eventy z różnych jachtów mają różne kolory (paleta).
|
||||
- Pierwszy/ostatni dzień rezerwacji wizualnie wypełniony do połowy (gradient/half cell).
|
||||
- Brak konsoli błędów JS.
|
||||
- Widget pojawia się w panelu Elementor pod kategorią pluginu.
|
||||
</verify>
|
||||
<done>AC-5 satisfied (półdniowe rendery + legenda + read-only). AC-6 deterministyczna paleta wspólna z REST.</done>
|
||||
</task>
|
||||
|
||||
<task type="checkpoint:human-verify" gate="blocking">
|
||||
<what-built>
|
||||
- Settings: nowa opcja "Tryb synchronizacji iCal" (per_yacht / global)
|
||||
- iCal Import: tryb global importuje wszystkie eventy bez filtrowania, nie blokuje dostępności jachtów
|
||||
- REST: `GET /availability/all` zwraca wszystkie rezerwacje + globalne eventy z kolorami i timed (12:00)
|
||||
- Frontend: shortcode `[yacht_calendar_all]` + widget Elementor "Yacht Calendar (wszystkie jachty)" z efektem half-day i legendą kolorów
|
||||
</what-built>
|
||||
<how-to-verify>
|
||||
1. Deploy plików przez FTP (ftp-kr) i ewentualnie aktywuj plugin (jeśli wymagane przez Installer dla nowej opcji).
|
||||
2. Wejdź w WP Admin → Yacht Booking → Settings → sekcja Synchronizacja: ustaw "Wspólny kalendarz", podaj URL feedu (lub tymczasowo `D:\temp\basic.ics` wystawiony przez serwer testowy), zapisz.
|
||||
3. Uruchom ręcznie `yacht_booking_ical_global_import` (np. WP-CLI: `wp cron event run yacht_booking_ical_global_import` lub przycisk "Synchronizuj teraz" jeśli istnieje).
|
||||
4. Sprawdź WP Admin → Bookings: powinny pojawić się ~30 wydarzeń bez yacht_id.
|
||||
5. Zweryfikuj że dostępność jachtów (kalendarz pojedynczego jachtu) się NIE zmieniła.
|
||||
6. Stwórz testową stronę z `[yacht_calendar_all]`. Otwórz w przeglądarce.
|
||||
7. Sprawdź: a) różne kolory dla "Maja" i "Kubuś", b) szare dla globalnych, c) pierwszy/ostatni dzień rezerwacji wypełniony do połowy, d) brak ukośników, e) legenda widoczna.
|
||||
8. Przełącz tryb na "Per jacht", uruchom cron — sprawdź że stary mechanizm nadal działa (matching po prefiksie, wpisy w availability).
|
||||
</how-to-verify>
|
||||
<resume-signal>Type "approved" to continue, or describe issues to fix</resume-signal>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<boundaries>
|
||||
|
||||
## DO NOT CHANGE
|
||||
- `frontend/class-calendar-widget.php` (istniejący widget per-jacht — kopiujemy NOWY plik, nie dotykamy starego)
|
||||
- `assets/js/calendar.js`, `assets/css/calendar.css` (assety istniejącego widgetu)
|
||||
- Schema tabeli `wp_yacht_availability` — nie dodajemy kolumn
|
||||
- `Booking::create()` flow (REST POST /bookings) — flow rezerwacji frontendowej bez zmian
|
||||
- Settings: nie zmieniamy domyślnej wartości `ical_sync_mode` na `global` (regresja). Default = `per_yacht`.
|
||||
- Stała `ICal_Import::GLOBAL_IMPORT_SOURCE = 'ical_import_global'` (per-jacht stale cleanup) — dodajemy DRUGĄ stałą `GLOBAL_CALENDAR_SOURCE = 'ical_global_calendar'`, nie zmieniamy istniejącej
|
||||
|
||||
## SCOPE LIMITS
|
||||
- Brak konfigurowalnej palety kolorów (color picker per jacht) — auto paleta z hardcoded tablicy. Color picker w meta jachtu = osobny plan jeśli klient zechce.
|
||||
- Brak osobnego widoku "tylko globalne wydarzenia" — globalne pokazują się tylko na nowym wspólnym widgecie.
|
||||
- Brak konfiguracji shortcode (atrybuty `yachts=`, `view=`) — wszystkie publikowane, dayGridMonth.
|
||||
- Brak klikalności dnia / formularza rezerwacji na nowym widgecie — read-only podgląd.
|
||||
- Brak migracji istniejących bookingów `_booking_source = ical_import_global` na nowy storage. Klient musi ręcznie usunąć stare jeśli przełączy się trwale na global.
|
||||
- Bez zmian dla widgetu Elementor istniejącego (per-jacht) — dwa widgety obok siebie.
|
||||
|
||||
</boundaries>
|
||||
|
||||
<verification>
|
||||
Before declaring plan complete:
|
||||
- [ ] `php -l` na każdym zmienionym/nowym pliku PHP — bez błędów
|
||||
- [ ] `wp option get yacht_booking_ical_sync_mode` zwraca poprawną wartość po zapisie
|
||||
- [ ] W trybie `global` po cron-imporcie liczba wydarzeń w `Bookings` ≈ liczba VEVENT z feedu (poza past)
|
||||
- [ ] W trybie `global` brak wpisów do `wp_yacht_availability` dla `_booking_source = ical_global_calendar`
|
||||
- [ ] W trybie `per_yacht` zachowanie identyczne jak przed planem (regression check)
|
||||
- [ ] `GET /availability/all` zwraca poprawny JSON dla niezalogowanego klienta
|
||||
- [ ] Strona z `[yacht_calendar_all]` renderuje się bez błędów JS w konsoli
|
||||
- [ ] Half-day visual widoczny na pierwszym i ostatnim dniu każdej rezerwacji
|
||||
- [ ] Legenda kolorów spójna z kolorami eventów
|
||||
- [ ] Wszystkie acceptance criteria spełnione
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- Klient może przełączyć tryb sync w settings i zobaczyć efekt po cron-imporcie
|
||||
- Wszystkie eventy z basic.ics (32) są zaimportowane w trybie global (poza past events)
|
||||
- Nowy widget pokazuje wszystkie jachty + globalne eventy z kolorami i half-day
|
||||
- Brak regresji w trybie per-jacht
|
||||
- Brak regresji w istniejącym widgecie per-jacht
|
||||
- Brak nowych ostrzeżeń PHP / błędów konsoli
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.paul/phases/09-finalizacja/09-04-SUMMARY.md`
|
||||
</output>
|
||||
Reference in New Issue
Block a user