Files
2026-05-10 15:08:40 +02:00

13 KiB

phase, plan, type, wave, depends_on, files_modified, autonomous, delegation
phase plan type wave depends_on files_modified autonomous delegation
09-finalizacja 07 execute 1
wp-content/plugins/yacht-booking-system/includes/class-yacht.php
wp-content/plugins/yacht-booking-system/admin/class-admin.php
wp-content/plugins/yacht-booking-system/admin/views/yacht-edit.php
wp-content/plugins/yacht-booking-system/api/class-rest-controller.php
wp-content/plugins/yacht-booking-system/frontend/class-calendar-widget-all.php
wp-content/plugins/yacht-booking-system/yacht-booking-system.php
.paul/ROADMAP.md
false off
## Goal Dodać administracyjny wybór koloru per jacht (`_yacht_color`) i zastosować go w widgecie zbiorczym `/rezerwacja/`. Dla rezerwacji bez przypisanego `yacht_id` (eventy z globalnego Google Calendar, source=`ical_global_calendar`) dopasować jacht po występowaniu jego nazwy/aliasu w tytule rezerwacji (case-insensitive, w dowolnym miejscu) i pokolorować event kolorem tego jachtu.

Purpose

Klient chce rozróżniać jachty wzrokiem w jednym wspólnym kalendarzu — obecnie kolory są przydzielane automatycznie z palety i nie ma kontroli nad wyborem; dodatkowo eventy z globalnego GCal lecą jednym kolorem GLOBAL_EVENT_COLOR, mimo że tytuł zawiera nazwę jachtu.

Output

  • Pole color picker w formularzu jachtu (yacht-edit.php) zapisywane do meta _yacht_color
  • Backend Rest_Controller::get_yacht_color_palette() honoruje meta _yacht_color z fallbackiem na obecną paletę (deterministyczna paleta po yacht_id zachowana dla braków)
  • get_all_availability() dla eventów is_global_event === true próbuje dopasować jacht po nazwie/aliasie w post_title rezerwacji i ustawia color + dodaje yacht_id do eventu (tylko do kolorystyki frontendu, bez zmiany danych w DB)
  • Legenda widgetu zbiorczego pokazuje wybrane kolory
  • ROADMAP zaktualizowany: 09-07 = ten plan, 09-08 = security audit, 09-09 = testy/tłumaczenia/dokumentacja
- **Numer planu** — Gdzie ten plan wpasować w roadmapę fazy 9? → Odpowiedź: 09-07 (przed security audit). Security przesuwamy na 09-08, dokumentacja na 09-09. - **Fallback** — Jak ma działać brak ustawionego koloru? → Odpowiedź: Auto z palety (jak teraz, deterministycznie po `yacht_id`). - **Zakres** — Czy kolor stosować również w widgecie pojedynczego jachtu? → Odpowiedź: Tylko zbiorczy (`/rezerwacja/`). Pojedynczy widget bez zmian. - **Global iCal** — Czy eventy z yacht_id=0 mają korzystać z koloru jachtu? → Odpowiedź: Tak — nazwa jachtu może wystąpić w dowolnym miejscu w tytule rezerwacji (case-insensitive, substring). Najdłuższe trafienie wygrywa, brak trafienia → `GLOBAL_EVENT_COLOR`.

Project Context

@.paul/PROJECT.md @.paul/ROADMAP.md @.paul/STATE.md

Source Files

@wp-content/plugins/yacht-booking-system/api/class-rest-controller.php @wp-content/plugins/yacht-booking-system/frontend/class-calendar-widget-all.php @wp-content/plugins/yacht-booking-system/admin/views/yacht-edit.php @wp-content/plugins/yacht-booking-system/admin/class-admin.php @wp-content/plugins/yacht-booking-system/includes/class-yacht.php @wp-content/plugins/yacht-booking-system/integrations/ical/class-ical-import.php

<acceptance_criteria>

AC-1: Admin może wybrać kolor jachtu

Given administrator otwiera formularz edycji jachtu (yacht-edit.php)
When wybierze kolor w polu "Kolor jachtu w kalendarzu zbiorczym" i zapisze formularz
Then meta `_yacht_color` jachtu zostaje zapisana jako sanitowany hex (`#rrggbb`)
And po przeładowaniu formularza widzi zapisany kolor w polu

AC-2: Kolor admina ma priorytet w widgecie zbiorczym

Given jacht ma ustawione `_yacht_color = #ff6600`
When frontend pobiera `GET /availability/all`
Then eventy tego jachtu (yacht_id > 0) mają `backgroundColor = #ff6600`
And legenda widgetu pokazuje kolor #ff6600 obok jego nazwy

AC-3: Fallback z palety dla jachtów bez ustawionego koloru

Given jacht nie ma `_yacht_color` (brak meta lub pusta wartość)
When frontend pobiera `GET /availability/all`
Then eventy tego jachtu otrzymują kolor z `YACHT_COLOR_PALETTE` (deterministycznie po posortowanym yacht_id, jak obecnie)

AC-4: Globalne eventy GCal kolorowane po nazwie jachtu w tytule

Given event z globalnego kalendarza (yacht_id=0, source=`ical_global_calendar`) o tytule "Rezerwacja - Maja - Kowalski"
And istnieje jacht o `post_title = "Maja"` z kolorem `#3498db` (lub fallback z palety)
When frontend pobiera `GET /availability/all`
Then ten event ma `backgroundColor = #3498db`
And jeśli żadna nazwa/alias jachtu nie pojawia się w tytule → `backgroundColor = GLOBAL_EVENT_COLOR`
And gdy w tytule pasuje wiele nazw → wybierany jest najdłuższy (np. "Maja Bis" wygrywa z "Maja")

</acceptance_criteria>

Task 1: Pole koloru w formularzu jachtu + meta `_yacht_color` wp-content/plugins/yacht-booking-system/admin/views/yacht-edit.php, wp-content/plugins/yacht-booking-system/admin/class-admin.php, wp-content/plugins/yacht-booking-system/includes/class-yacht.php, wp-content/plugins/yacht-booking-system/yacht-booking-system.php 1. `class-yacht.php`: dodaj statyczne metody `get_color( $yacht_id ): string` (zwraca '' gdy brak meta) i `update_color( $yacht_id, $color )` z sanityzacją do `#rrggbb` (regex `/^#[0-9a-f]{6}$/i`, lowercase). Klucz meta: `_yacht_color`. 2. `admin/views/yacht-edit.php`: w sekcji ustawień jachtu dodaj pole `` z labelem "Kolor jachtu (kalendarz zbiorczy)". Pod inputem krótki tekst pomocniczy: "Pozostaw puste, aby użyć automatycznego koloru z palety." 3. `class-admin.php` → `save_yacht()`: po istniejących wpisach meta wywołaj `Yacht::update_color( $saved_id, $_POST['yacht_color'] ?? '' )`. Pusty string usuwa meta (delete_post_meta). 4. `class-admin.php` → `enqueue_admin_assets()` lub punkt rejestrujący style admin: na stronie `yacht-bookings-add-yacht` enqueue `wp-color-picker` (style + script) oraz inline init: `jQuery('.yacht-color-picker').wpColorPicker();`. Inline JS wpięty przez `wp_add_inline_script( 'wp-color-picker', ... )`. Avoid: zapisywanie surowej wartości z $_POST bez sanityzacji; nadpisywanie istniejącej meta gdy POST nie zawiera `yacht_color` (ale tutaj formularz zawsze wysyła to pole). Edytuj jacht w panelu, ustaw kolor `#ff6600`, zapisz. Sprawdź `wp_postmeta`: `meta_key = _yacht_color`, `meta_value = #ff6600`. Wyczyść pole, zapisz → meta usunięta. `php -l` na każdym zmienionym pliku. AC-1 satisfied. Task 2: Backend — `_yacht_color` w palecie + matching globalnych eventów po nazwie wp-content/plugins/yacht-booking-system/api/class-rest-controller.php 1. `get_yacht_color_palette( $yacht_ids )`: dla każdego `yacht_id` najpierw spróbuj `Yacht::get_color( $yacht_id )`; jeśli niepuste — użyj. Inaczej fallback na obecny algorytm `palette[i % count]` (i = pozycja w posortowanej tablicy ID, jak teraz). Wynik nadal `array`. 2. `get_all_availability()`: zbuduj mapę dopasowań nazwa→yacht_id raz przed pętlą eventów: - Pobierz wszystkie publish jachty z polami `ID, post_title`. - Dla każdego: dodaj wpis `[strtolower(post_title) => yacht_id]` oraz, jeśli `Yacht::get_gcal_alias($id)` niepusty, `[strtolower($alias) => yacht_id]`. - Posortuj klucze malejąco po długości (najdłuższy match wygrywa). 3. W pętli eventów, gdy `$is_global_event === true` (yacht_id=0 lub source=GLOBAL_CALENDAR_SOURCE): - Weź `post_title` rezerwacji (`$booking->post_title`), zlowercase'uj. - Iteruj po posortowanej liście kluczy; pierwszy `mb_strpos($title_lower, $key) !== false` wygrywa → `$matched_yacht_id = mapa[key]`. - Jeśli match → `$color = $color_map[$matched_yacht_id] ?? GLOBAL_EVENT_COLOR`. Brak → `$color = GLOBAL_EVENT_COLOR` (jak teraz). - Nie modyfikuj `yacht_id` w odpowiedzi (zostaje 0); kolor wystarczy do wizualizacji. 4. Zachowaj obecne zachowanie dla eventów per-yacht (`yacht_id > 0`) bez zmian. Avoid: case-sensitive porównań; budowania mapy w pętli (perf); modyfikowania danych eventu poza polem `color`. `php -l class-rest-controller.php`. Ręcznie: `curl '/wp-json/yacht-booking/v1/availability/all?start=2026-05-01&end=2026-06-01' | jq '.[] | {title, color}'` — eventy globalne z nazwą jachtu w tytule mają kolor jachtu, bez nazwy → `#7fb3d5`. Per-yacht jachty z ustawionym `_yacht_color` mają ten kolor. AC-2, AC-3, AC-4 satisfied. Task 3: Legenda widgetu zbiorczego + ROADMAP update wp-content/plugins/yacht-booking-system/frontend/class-calendar-widget-all.php, .paul/ROADMAP.md 1. `class-calendar-widget-all.php`: linia ~149-179 — `get_yacht_color_palette()` po Task 2 już honoruje `_yacht_color`, więc legenda dostanie poprawne kolory bez zmian logiki. Zweryfikuj że `$color_map` przekazywana do legendy jest taką samą referencją (jeśli nie — ujednolicić). Jeśli logika legendy oczekuje `palette[i % count]`, zaktualizować by używała tej samej funkcji co backend. 2. `.paul/ROADMAP.md`: w sekcji "Plans" Phase 9: - Dodaj `- [ ] 09-07: Kolory per jacht w kalendarzu zbiorczym (color picker + dopasowanie po nazwie)` - Przesuń istniejące: `09-07: Security audit` → `09-08`, `09-08: Testy + tłumaczenia + dokumentacja` → `09-09`. - Zaktualizuj nagłówek "Phases: 8 of 9 complete" oraz tabelę faz (Phase 9 plans count) jeśli to potrzebne. Avoid: dotykania STATE.md tutaj — to robi krok update_state w workflow. Otwórz `/rezerwacja/`, sprawdź wzrokowo: legenda u góry pokazuje kolory jachtów = wybranym w panelu (lub fallback z palety dla braków). `.paul/ROADMAP.md` zawiera 09-07 jako kolory, 09-08 jako security, 09-09 jako docs. AC-2 (legenda) satisfied; roadmap zsynchronizowany z planem. Pole koloru w formularzu jachtu + zastosowanie kolorów w widgecie zbiorczym (`/rezerwacja/`) z dopasowaniem nazwy jachtu w tytule eventów globalnych. 1. Wejdź do panelu admina → Jachty → wybierz dwa jachty, ustaw różne kolory (np. `#ff6600`, `#1abc9c`). Trzeci zostaw bez koloru. 2. Odśwież `https://jachty3.pagedev.pl/rezerwacja/`. 3. Sprawdź: - Rezerwacje pierwszych dwóch jachtów mają wybrane kolory. - Rezerwacje trzeciego jachtu mają kolor z palety (auto). - Eventy z globalnego GCal, których tytuł zawiera nazwę jednego z dwóch pierwszych jachtów, też dostają jego kolor. - Legenda u góry kalendarza zbiorczego pokazuje te same kolory. 4. Wyczyść kolor jednego jachtu w panelu, zapisz, odśwież `/rezerwacja/` → ten jacht wraca do koloru z palety. Wpisz "approved" aby zamknąć plan przez `/paul:unify`, lub opisz zaobserwowane problemy.

DO NOT CHANGE

  • wp-content/plugins/yacht-booking-system/integrations/ical/class-ical-import.php (per-yacht prefix matching pozostaje bez zmian — zmieniamy tylko prezentację w /availability/all)
  • wp_yacht_availability (schemat)
  • Pojedynczy widget jachtu (class-calendar-widget.php) — kolory tam bez zmian
  • Endpoint /availability/{yacht_id} — bez zmian
  • GLOBAL_EVENT_COLOR jako fallback (nadal #7fb3d5)
  • YACHT_COLOR_PALETTE jako fallback (nadal 8 hex)

SCOPE LIMITS

  • Bez migracji DB (meta dodawana on-demand przez update_post_meta)
  • Bez zmian w warstwie GCal sync (push/pull do Google) — kolory są tylko widoczne w naszym widgecie zbiorczym
  • Bez tłumaczeń pól (PL hardcoded; tłumaczenia objęte planem 09-09)
  • Bez zmian w endpointach REST poza get_all_availability()
  • Brak wsparcia dla CSS gradient/secondary color — jeden hex per jacht
- [ ] `php -l` przechodzi na wszystkich zmienionych plikach PHP - [ ] Po zapisie formularza jachtu z kolorem `_yacht_color` jest w `wp_postmeta` - [ ] Po wyczyszczeniu pola meta jest usuwana - [ ] `GET /wp-json/yacht-booking/v1/availability/all` zwraca `color` zgodny z meta lub paletą fallback - [ ] Globalne eventy GCal z nazwą jachtu w tytule kolorowane kolorem tego jachtu - [ ] Najdłuższe dopasowanie wygrywa (np. "Maja Bis" > "Maja") - [ ] Brak match → `GLOBAL_EVENT_COLOR` - [ ] Legenda widgetu zbiorczego spójna z kolorami eventów - [ ] ROADMAP.md odzwierciedla nową kolejność (07 kolory, 08 security, 09 docs) - [ ] Wszystkie kryteria akceptacji spełnione przy weryfikacji manualnej

<success_criteria>

  • Wszystkie zadania ukończone i zweryfikowane
  • Brak regresji w widgecie pojedynczego jachtu
  • Brak regresji w existing per-yacht iCal import (matching prefix nadal działa)
  • Klient akceptuje kolory na /rezerwacja/ </success_criteria>
Po ukończeniu utwórz `.paul/phases/09-finalizacja/09-07-SUMMARY.md`.