Files
2026-05-08 00:12:37 +02:00

9.1 KiB

phase, plan, subsystem, tags, requires, provides, affects, tech-stack, key-files, key-decisions, patterns-established, duration, started, completed
phase plan subsystem tags requires provides affects tech-stack key-files key-decisions patterns-established duration started completed
09-finalizacja 05 ui, api
fullcalendar
rest
privacy-revert
ux
phase provides
09-finalizacja widget zbiorczy [yacht_calendar_all] + REST /availability/all (09-04)
tytuły rezerwacji (raw SUMMARY z `_booking_notes` lub `customer_name`) widoczne na paskach kalendarza zbiorczego
per-day allDay events (każda doba rezerwacji = osobny pasek w swojej komórce)
half-day visual przeniesiony na flagi `extendedProps.is_first` / `is_last_night`
native tooltip na hover (title + data dnia)
security audit (09-06) — privacy hardening z 09-04 świadomie cofnięty
added patterns
allDay events per occupied day (start INCLUSIVE → end INCLUSIVE) zamiast jednej timed belki cross-midnight
extendedProps jako single source of truth dla half-day flag (server decyduje, JS renderuje)
native HTML title attribute jako tooltip (zero zależności, accessibility-friendly)
created modified
wp-content/plugins/yacht-booking-system/api/class-rest-controller.php
wp-content/plugins/yacht-booking-system/frontend/assets/js/calendar-all.js
wp-content/plugins/yacht-booking-system/frontend/assets/css/calendar-all.css
wp-content/plugins/yacht-booking-system/yacht-booking-system.php
Per-day allDay events zamiast 1 timed event 12:00→12:00 (poprzednia próba z timed eventami crossowała północ → FC renderował schodki)
Iteracja od start_date do end_date INCLUSIVE — pierwszy i ostatni dzień mają half-day visual
Cofnięcie privacy hardening z 09-04 — title z `_booking_notes` (iCal raw SUMMARY) lub `customer_name` widoczny publicznie per żądanie klienta
Tooltip = native `title` attribute (bez tippy.js / qtip — zero JS, działa offline)
extendedProps jako kontrakt server↔JS dla flag visual (kiedy is_start/is_end FC nie wystarcza)
Privacy w REST jest decyzją biznesową, nie techniczną — security audit musi to weryfikować osobno
~75min 2026-05-07T22:30:00Z 2026-05-07T23:50:00Z

Phase 09 Plan 05: UX rezerwacja — tytuły GCal + per-day segmenty

Kalendarz zbiorczy [yacht_calendar_all] na /rezerwacja/ pokazuje tytuły rezerwacji (raw SUMMARY z Google Calendar bez prefiksu "GCal:") na osobnych paskach per dzień, z half-day visual na pierwszym i ostatnim dniu rezerwacji oraz native tooltip na hover.

Performance

Metric Value
Duration ~75min (z 1 iteracją UX po pierwszym deploy)
Started 2026-05-07T22:30:00Z
Completed 2026-05-07T23:50:00Z
Tasks 4 auto + 1 checkpoint + 1 iteracja UX (allDay fix) + 1 mini-fix (tooltip)
Files modified 4

Acceptance Criteria Results

Criterion Status Notes
AC-1: Tytuł rezerwacji z iCal w REST Pass _booking_notes zwracane jako title, prefiks "GCal:" zniknął
AC-2: Tytuł rezerwacji frontowej Pass Booking::get_customer_name() jako fallback
AC-3: Tytuł renderowany w pasku eventu Pass .yc-event-title z ellipsis; weryfikacja Playwright (events: "Kubuś - Julia R")
AC-4: Per-day segmenty z gap Pass Po fix do allDay — każda doba w osobnej komórce, margin 2px daje gap
AC-5: Half-day visual zachowany Pass extendedProps.is_first / is_last_night sterują gradientem
AC-6: Privacy — brak email/phone Pass Payload REST nie zawiera customer_email ani customer_phone

Accomplishments

  • Tytuły rezerwacji widoczne — klient może wzrokowo identyfikować rezerwacje na publicznym kalendarzu (np. "Kubuś - Julia R", "Maja - Kowalscy 5 osób") bez prefiksu "GCal:".
  • Per-day allDay events — każda doba rezerwacji to osobny pasek w pojedynczej komórce dnia (1.06, 2.06, 3.06...) z 2px gapem między nimi. Rezerwacja 5-dniowa = 5 osobnych prostokątów zamiast jednej ciągłej belki.
  • Half-day visual zachowany — pierwszy dzień rezerwacji (yacht odbierany w południe) ma lewą połowę transparentną, ostatni dzień (zwrot w południe) prawą połowę transparentną. Środkowe dni — pełny kolor.
  • Native tooltip na hovertitle attribute z formatem "{tytuł} ({YYYY-MM-DD})" — zero zależności, działa accessibility-friendly.

Files Created/Modified

File Change Purpose
api/class-rest-controller.php Modified get_all_availability(): title z _booking_notes/customer_name, split per-day allDay events z extendedProps (is_first / is_last_night)
frontend/assets/js/calendar-all.js Modified eventContent renderuje .yc-event-title (escaped przez .text()); eventDidMount ustawia native title tooltip; applyHalfDayGradient czyta flagi z extendedProps
frontend/assets/css/calendar-all.css Modified Usunięte display:none z .fc-event-title; nowy .yc-event-title (ellipsis); margin: 1px 2px na .fc-daygrid-event (gap między paskami); mobile font-size
yacht-booking-system.php Modified Bump wersji 1.1.0 → 1.2.0 (cache busting)

Decisions Made

Decision Rationale Impact
Per-day allDay events zamiast timed 12:00→12:00 Pierwsza próba z timed eventami crossowała północ → FC dayGrid renderował każdą dobę jako pasek na granicy dwóch komórek (efekt "schodków") Każda doba zamknięta w jednej komórce, czysty layout
Iteracja start_date <= end_date (INCLUSIVE) Yacht obecny od noon dnia start do noon dnia end → wszystkie dni tego zakresu są "occupied" Rezerwacja 1.06 → 5.06 emituje 5 eventów (1, 2, 3, 4, 5) zamiast 4 nocy
Cofnięcie privacy z 09-04 Klient zmienił zdanie — chce wzrokowo identyfikować rezerwacje Tytuły widoczne publicznie. customer_email/customer_phone nadal NIE wychodzą przez REST. Security audit (09-06) musi to uwzględnić
Tooltip = native title attribute Klient prosił o "jakiś label na hover" — najprostsze, bez nowych zależności Hover po ~1s pokazuje "Kubuś - Julia R (2026-06-04)"

Deviations from Plan

Summary

Type Count Impact
Auto-fixed 1 Krytyczny: pierwsza wersja (timed events 12:00→12:00) renderowała "schodki" — zmiana na allDay events naprawiła layout
Scope additions 1 Native tooltip na hover (poza pierwotnym PLAN.md, prośba klienta po weryfikacji)
Deferred 0

Total impact: Pierwsza implementacja per-PLAN była technicznie poprawna (timed events 12:00→12:00 = 1 doba), ale FC dayGrid renderuje takie eventy jako rozciągnięte przez granicę dwóch komórek (każda doba pojawiała się na pograniczu dnia N i N+1). Fix do allDay events rozwiązał to zachowując semantykę (start/end INCLUSIVE).

Auto-fixed Issues

1. Timed events 12:00→12:00 renderowały "schodki" w FC dayGrid

  • Found during: Checkpoint human-verify (klient zgłosił "paski jakoś dziwnie wyszły")
  • Issue: Każdy event był 24h cross-midnight (start dzień N 12:00 → dzień N+1 12:00). FC dayGrid pokazywał każdą dobę jako fragment na granicy dwóch komórek, eventy nakładały się wizualnie tworząc efekt schodków
  • Fix: Zmiana na allDay: true z start = day (bez end). Iteracja od start_date do end_date INCLUSIVE. Każdy event w jednej komórce
  • Files: api/class-rest-controller.php (pętla while)
  • Verification: Playwright snapshot po deploy — paski wyrównane do komórek dni, brak nakładek
  • Commit: część zmiany w Task 1 (przed checkpointem) + redeploy po fix

Scope Additions

1. Native tooltip na hover

  • Origin: Po zatwierdzeniu allDay fix klient poprosił o "jakiś label na hover"
  • Implementation: info.el.setAttribute('title', info.event.title + ' (' + dayStr + ')') w eventDidMount
  • Verification: klient potwierdził OK
  • Files: frontend/assets/js/calendar-all.js

Deferred Items

None.

Issues Encountered

Issue Resolution
Timed events crossowały północ → "schodki" w grid Zmiana modelu na allDay events INCLUSIVE start↔end

Skill Audit

.paul/SPECIAL-FLOWS.md nie istnieje — skill audit pominięty.

Next Phase Readiness

Ready:

  • Widget zbiorczy [yacht_calendar_all] w pełni funkcjonalny — UX zatwierdzony przez klienta
  • Plugin v1.2.0 deployed
  • Privacy w REST świadomie zarządzona — security audit (09-06) ma jasny precedens do oceny

Concerns:

  • Privacy regression vs 09-04_booking_notes (raw iCal SUMMARY) i customer_name są teraz publicznie wystawiane na /availability/all. Klient zaakceptował biznesowo. Security audit (09-06) powinien:
    1. Potwierdzić że customer_email/customer_phone nadal NIE wyciekają (są zablokowane na poziomie REST shape).
    2. Rozważyć czy tytuły rezerwacji (zawierające imiona/nazwiska klientów) wymagają dodatkowych zabezpieczeń (np. throttling, robots noindex na endpoincie REST).
  • Brak automatycznych testów regresji — przy kolejnych zmianach w get_all_availability() regresja może umknąć

Blockers:

  • None

Phase: 09-finalizacja, Plan: 05 Completed: 2026-05-07