--- phase: 09-finalizacja plan: 07 subsystem: ui tags: [color-picker, fullcalendar, wp-color-picker, ical-global, branding] requires: - phase: 09-finalizacja provides: Widget zbiorczy `/rezerwacja/`, REST `/availability/all` z paletą kolorów per-jacht (09-04) provides: - Admin color picker per jacht (meta `_yacht_color`) - Honor `_yacht_color` w `Rest_Controller::get_yacht_color_palette()` z fallbackiem na paletę - Substring matching nazwy/aliasu jachtu w tytule globalnych eventów GCal (longest-match wins) - Legenda widgetu zbiorczego pokazuje per-yacht kolory także w trybie global - Proporcje 2fr:1fr w `.yacht-inquiry-layout` (kalendarz : formularz) - Zmniejszony padding w paskach eventów + wyśrodkowanie tekstu (poziomo + pionowo) affects: [09-08 security audit, 09-09 docs/translations] tech-stack: added: [] patterns: - Per-yacht admin meta z fallbackiem na deterministyczną paletę - Name/alias matching dla bookings yacht_id=0 (longest-match-first) key-files: created: [] modified: - wp-content/plugins/yacht-booking-system/includes/class-yacht.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-booking.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/frontend/assets/css/calendar.scss - wp-content/plugins/yacht-booking-system/frontend/assets/css/calendar.css - wp-content/plugins/yacht-booking-system/frontend/assets/css/calendar-all.css key-decisions: - "Fallback z palety zachowany — admin color jest opcjonalny, brak meta = paleta po posortowanym yacht_id" - "Matching globalnych eventów po substring w tytule (case-insensitive, mb_*), longest match wygrywa" - "Drop is_global_mode override w get_all_availability — kolory działają niezależnie od trybu sync" - "Proporcje layoutu zbiorczego 2fr:1fr (poprzednio 1fr:1fr) per żądanie klienta" patterns-established: - "Per-yacht admin overrides z fallbackiem na deterministyczny algorytm po ID" duration: ~50min started: 2026-05-10T00:00:00Z completed: 2026-05-10T00:50:00Z --- # Phase 09 Plan 07: Kolory per jacht w kalendarzu zbiorczym **Admin może wybrać kolor jachtu w panelu, eventy z globalnego GCal dopasowują się do jachtu po nazwie/aliasie w tytule. Layout `/rezerwacja/` przeskalowany 2:1 na korzyść kalendarza.** ## Performance | Metric | Value | |--------|-------| | Duration | ~50 min | | Started | 2026-05-10 | | Completed | 2026-05-10 | | Tasks | 3 auto + 1 checkpoint approved | | Files modified | 9 | ## Acceptance Criteria Results | Criterion | Status | Notes | |-----------|--------|-------| | AC-1: Admin może wybrać kolor jachtu | Pass | `_yacht_color` zapisywane przez `Yacht::update_color()`, walidacja regex `#rrggbb`, color picker przez `wp-color-picker` | | AC-2: Kolor admina ma priorytet w widgecie zbiorczym | Pass | `get_yacht_color_palette()` honoruje meta przed paletą, legenda używa tej samej funkcji | | AC-3: Fallback z palety dla jachtów bez koloru | Pass | Brak meta → `palette[i % count]` po posortowanym ID (deterministycznie) | | AC-4: Globalne eventy GCal kolorowane po nazwie | Pass | `name_map` z `post_title` + `_yacht_gcal_alias`, sort DESC po długości, `mb_strpos` case-insensitive | ## Accomplishments - Color picker WP w formularzu jachtu z meta `_yacht_color` (sanityzacja `#rrggbb`, pusta wartość usuwa meta) - Backend z dwupoziomową logiką kolorów: per-yacht event → admin color/paleta; global event (yacht_id=0) → match po nazwie w tytule (longest-match-first) - Legenda widgetu zbiorczego pokazuje teraz wszystkie jachty z ich kolorami, niezależnie od trybu sync (+ "Inne" jako fallback w trybie global) - Layout `/rezerwacja/` przeskalowany do 2fr:1fr — więcej miejsca dla kalendarza - Paski eventów: padding zredukowany (`2px 4px` → `0 1px`), tytuł wyśrodkowany w poziomie (`text-align:center`) i w pionie (`display:flex; align-items:center` na `.fc-event` i `.fc-event-main`) ## Files Created/Modified | File | Change | Purpose | |------|--------|---------| | `includes/class-yacht.php` | Modified | Dodane `get_color()` / `update_color()` ze sanityzacją hex | | `admin/views/yacht-edit.php` | Modified | Pole color picker + label + opis | | `admin/class-admin.php` | Modified | `save_yacht()` zapisuje meta `_yacht_color` | | `includes/class-yacht-booking.php` | Modified | Enqueue `wp-color-picker` + inline init na stronie edycji jachtu | | `api/class-rest-controller.php` | Modified | `get_yacht_color_palette()` honoruje admin color; `get_all_availability()` dopasowuje globalne eventy po nazwie | | `frontend/class-calendar-widget-all.php` | Modified | Legenda zawsze per-yacht; "Inne" jako fallback w trybie global | | `frontend/assets/css/calendar.scss` | Modified | `.yacht-inquiry-layout` `1fr 1fr` → `2fr 1fr` | | `frontend/assets/css/calendar.css` | Modified | Skompilowane CSS (calendar.scss) | | `frontend/assets/css/calendar-all.css` | Modified | Padding eventów + flex-center poziomo i pionowo | | `.paul/ROADMAP.md` | Modified | 09-07 nowy plan, security przesunięty na 09-08, docs na 09-09 | ## Decisions Made | Decision | Rationale | Impact | |----------|-----------|--------| | Fallback z palety zachowany | Niski próg wejścia — admin nie musi ustawiać koloru by system działał | Spójność wsteczna z 09-04 | | Matching globalnych eventów: substring + longest-match | Klient: "naprostsze wyszukiwanie nazwy w tytule" — nazwa może być w dowolnym miejscu, najdłuższe trafienie wygrywa (np. "Maja Bis" > "Maja") | Eventy z wspólnego GCal automatycznie kolorowane bez zmian w schemacie DB | | Drop `is_global_mode` override | Wcześniej w trybie global wszystkie eventy szły `GLOBAL_EVENT_COLOR` ignorując yacht_id; klient chce kolory zawsze | Tryb global = pełna kolorystyka (bonus poza pierwotnym scope) | | Layout 2fr:1fr | Klient: "kalendarz 2/3, formularz 1/3" | Mobile breakpoint @992px nadal stackuje | ## Deviations from Plan ### Summary | Type | Count | Impact | |------|-------|--------| | Auto-fixed | 0 | — | | Scope additions | 4 | Bonus UX poprawki, niski risk | | Deferred | 0 | — | **Total impact:** Plan zrealizowany w pełni + 4 dodatkowe poprawki UX zgłoszone w trakcie checkpoint review (proporcje 2:1, padding pasków, wyrównanie poziome i pionowe tekstu). ### Scope Additions **1. Layout proportions 2fr:1fr (`/rezerwacja/`)** - Found during: Po approve checkpoint - Change: `.yacht-inquiry-layout` z `1fr 1fr` na `2fr 1fr` w SCSS i skompilowanym CSS - Files: `calendar.scss`, `calendar.css` - Verification: Wzrokowo na `/rezerwacja/` po deploy **2. Padding pasków eventów** - Found during: Po approve checkpoint - Change: `.fc-event` `2px 4px` → `0 1px`, `.yc-event-title` `1px 6px` → `0 2px`, margin pasków `1px 2px` → `1px 0` - Files: `calendar-all.css` - Verification: Więcej miejsca na tekst tytułu rezerwacji **3. Tekst tytułu wyśrodkowany poziomo** - Found during: Po zmianie paddingu - Change: `text-align: center` + `width: 100%` na `.yc-event-title` - Files: `calendar-all.css` **4. Tekst tytułu wyśrodkowany pionowo** - Found during: Po zmianie poziomej - Change: `display:flex; align-items:center` na `.fc-event` i `.fc-event-main` - Files: `calendar-all.css` ### Deferred Items None. ## Issues Encountered None — wszystkie zmiany przeszły `php -l` bez błędów, layout zachowany. ## Next Phase Readiness **Ready:** - Plan 09-08 (Security audit) — endpoint `/availability/all` ma teraz dodatkową logikę matchingu nazw, do oceny w audycie (escapowanie tytułów, performance pętli `mb_strpos`) - Plan 09-09 (Testy + tłumaczenia + docs) — nowe stringi w yacht-edit.php (label, description) wymagają wpisów w .pot **Concerns:** - Skompilowany `calendar.css` jest plikiem ręcznie edytowanym (brak workflow build) — zmiany w SCSS i CSS muszą być synchronizowane manualnie. Do udokumentowania w 09-09. - `name_map` w `get_all_availability()` budowana per-request — przy dużej liczbie jachtów + długim oknie czasowym może wpłynąć na performance. Aktualnie pomijalne (kilka jachtów). **Blockers:** None. --- *Phase: 09-finalizacja, Plan: 07* *Completed: 2026-05-10*