feat(07-hero-search-form): Mini formularz rezerwacji w hero z pre-fill do modala
Phase 7 complete: - Nowy widget Elementor "Carei Search Form" do osadzenia w hero - Pola: segment, daty od/do, lokalizacja, checkbox zwrotu - Po kliknięciu przycisku otwiera modal z pre-wypełnionymi danymi - Design zgodny z Figmą (tło #EDEDF3, przycisk czerwony, tytuł fioletowy) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
263
.paul/phases/07-hero-search-form/07-01-PLAN.md
Normal file
263
.paul/phases/07-hero-search-form/07-01-PLAN.md
Normal file
@@ -0,0 +1,263 @@
|
||||
---
|
||||
phase: 07-hero-search-form
|
||||
plan: 01
|
||||
type: execute
|
||||
wave: 1
|
||||
depends_on: []
|
||||
files_modified:
|
||||
- wp-content/plugins/carei-reservation/includes/class-search-widget.php
|
||||
- wp-content/plugins/carei-reservation/assets/css/carei-reservation.css
|
||||
- wp-content/plugins/carei-reservation/assets/js/carei-reservation.js
|
||||
- wp-content/plugins/carei-reservation/carei-reservation.php
|
||||
autonomous: false
|
||||
---
|
||||
|
||||
<objective>
|
||||
## Goal
|
||||
Nowy widget Elementor "Carei Search Form" — kompaktowy mini formularz rezerwacji do osadzenia w sekcji hero. Po wypełnieniu i kliknięciu przycisku otwiera istniejący popup formularza rezerwacji z automatycznie uzupełnionymi danymi (segment, daty, lokalizacja).
|
||||
|
||||
## Purpose
|
||||
Użytkownik widzi formularz już na hero — nie musi szukać przycisku rezerwacji. Skraca ścieżkę konwersji i daje natychmiastowe CTA.
|
||||
|
||||
## Output
|
||||
- Nowy plik: `class-search-widget.php` (widget Elementor)
|
||||
- Rozszerzony CSS: style mini formularza
|
||||
- Rozszerzony JS: logika prefill + otwarcie modala z danymi z mini formularza
|
||||
- Rejestracja widgetu w `carei-reservation.php`
|
||||
</objective>
|
||||
|
||||
<context>
|
||||
## Project Context
|
||||
@.paul/PROJECT.md
|
||||
@.paul/ROADMAP.md
|
||||
|
||||
## Source Files
|
||||
@wp-content/plugins/carei-reservation/carei-reservation.php
|
||||
@wp-content/plugins/carei-reservation/includes/class-elementor-widget.php
|
||||
@wp-content/plugins/carei-reservation/assets/js/carei-reservation.js
|
||||
@wp-content/plugins/carei-reservation/assets/css/carei-reservation.css
|
||||
</context>
|
||||
|
||||
<acceptance_criteria>
|
||||
|
||||
## AC-1: Widget renderuje mini formularz
|
||||
```gherkin
|
||||
Given strona z osadzonym widgetem "Carei Search Form" w Elementorze
|
||||
When strona się ładuje
|
||||
Then widoczny jest kompaktowy formularz z polami: segment (select), daty od/do, miejsce odbioru (select), checkbox "Zwrot w tej samej lokalizacji", przycisk "Złóż zapytanie o rezerwację"
|
||||
```
|
||||
|
||||
## AC-2: Selecty ładują dane z API
|
||||
```gherkin
|
||||
Given mini formularz jest widoczny na stronie
|
||||
When strona się załadowała
|
||||
Then select segmentu zawiera segmenty z API (segments-branches-map)
|
||||
And select lokalizacji filtruje się po wybranym segmencie
|
||||
```
|
||||
|
||||
## AC-3: Przycisk otwiera modal z pre-wypełnionymi danymi
|
||||
```gherkin
|
||||
Given użytkownik wypełnił mini formularz (segment, daty, lokalizacja)
|
||||
When kliknie "Złóż zapytanie o rezerwację"
|
||||
Then otwiera się istniejący modal rezerwacji
|
||||
And pola segment, data od, data do, miejsce odbioru są automatycznie wypełnione wartościami z mini formularza
|
||||
And checkbox zwrotu jest zsynchronizowany
|
||||
And extras/pricelist ładują się automatycznie (jak po ręcznym wypełnieniu)
|
||||
```
|
||||
|
||||
## AC-4: Design zgodny z Figmą
|
||||
```gherkin
|
||||
Given mini formularz jest renderowany
|
||||
When wyświetla się na desktop
|
||||
Then tło #EDEDF3, zaokrąglone rogi 14px, border #2F2482/10%
|
||||
And pola mają białe tło, zaokrąglone rogi
|
||||
And przycisk jest czerwony (#FF0000) z białym tekstem, pełna szerokość
|
||||
And font Albert Sans, tytuł bold fioletowy (#2F2482)
|
||||
```
|
||||
|
||||
</acceptance_criteria>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Widget Elementor + HTML mini formularza</name>
|
||||
<files>wp-content/plugins/carei-reservation/includes/class-search-widget.php, wp-content/plugins/carei-reservation/carei-reservation.php</files>
|
||||
<action>
|
||||
1. Utworzyć `class-search-widget.php` z klasą `Carei_Search_Widget extends \Elementor\Widget_Base`:
|
||||
- name: `carei-search-form`
|
||||
- title: `Carei Search Form`
|
||||
- icon: `eicon-search`
|
||||
- categories: `['general']`
|
||||
- style/script depends: te same co główny widget (carei-reservation-css, carei-reservation-js)
|
||||
- Brak kontrolek Elementor (formularz jest statyczny)
|
||||
|
||||
2. Metoda `render()` generuje HTML:
|
||||
- Container `div.carei-search-form` z tłem
|
||||
- Tytuł: `<h2 class="carei-search-form__title">Wypełnij formularz rezerwacji<span>.</span></h2>`
|
||||
- Select segmentu: `<select id="carei-search-segment">` z placeholder "Wybierz segment" i ikoną strzałki
|
||||
- Wiersz z dwoma polami daty: `<input type="datetime-local" id="carei-search-date-from">` i `id="carei-search-date-to"` z ikonkami kalendarza i labelami "Od kiedy?" / "Do kiedy?"
|
||||
- Select lokalizacji: `<select id="carei-search-pickup">` z ikoną pinu i placeholder "Miejsce odbioru"
|
||||
- Checkbox: `<input type="checkbox" id="carei-search-same-return" checked>` z label "Zwrot w tej samej lokalizacji"
|
||||
- Przycisk: `<button type="button" class="carei-search-form__submit" id="carei-search-submit">` z tekstem "Złóż zapytanie o rezerwację"
|
||||
|
||||
3. Zarejestrować widget w `carei-reservation.php`:
|
||||
- Dodać `require_once` w callbacku `elementor/widgets/register`
|
||||
- `$widgets_manager->register( new Carei_Search_Widget() );`
|
||||
|
||||
Avoid: Duplikowanie modala — mini formularz NIE zawiera modala. Modal jest renderowany przez istniejący widget Carei Reservation, który musi być obecny na tej samej stronie.
|
||||
</action>
|
||||
<verify>Widget "Carei Search Form" widoczny w panelu Elementor, po osadzeniu renderuje HTML mini formularza</verify>
|
||||
<done>AC-1 satisfied: Mini formularz renderuje się z wszystkimi polami</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: JavaScript — ładowanie danych + prefill + otwarcie modala</name>
|
||||
<files>wp-content/plugins/carei-reservation/assets/js/carei-reservation.js</files>
|
||||
<action>
|
||||
1. W sekcji inicjalizacji (DOMContentLoaded) dodać wykrywanie mini formularza:
|
||||
```
|
||||
var searchForm = document.querySelector('.carei-search-form');
|
||||
```
|
||||
Jeśli istnieje, zainicjalizować `initSearchForm()`.
|
||||
|
||||
2. Funkcja `initSearchForm()`:
|
||||
- Pobrać referencje do elementów: `carei-search-segment`, `carei-search-date-from`, `carei-search-date-to`, `carei-search-pickup`, `carei-search-same-return`
|
||||
- Załadować dane API (segments-branches-map) — REUŻYĆ istniejącą logikę `loadInitialData`, ale populować selecty mini formularza
|
||||
- Podpiąć event na zmianę segmentu → filtrowanie lokalizacji (jak w głównym formularzu)
|
||||
- Podpiąć event na `#carei-search-submit` click:
|
||||
a) Zebrać wartości z mini formularza
|
||||
b) Znaleźć overlay modala: `document.querySelector('[data-carei-modal]')`
|
||||
c) Wywołać `openModal()` (istniejąca funkcja)
|
||||
d) Po otwarciu modala (setTimeout ~100ms po openModal) ustawić wartości w głównym formularzu:
|
||||
- `segmentSelect.value = searchSegment` + dispatch 'change' event
|
||||
- `dateFrom.value = searchDateFrom` + dispatch 'change'
|
||||
- `dateTo.value = searchDateTo` + dispatch 'change'
|
||||
- `pickupSelect` — poczekać aż lokalizacje się załadują po change segmentu, potem ustawić wartość
|
||||
- `sameReturnCheck.checked = searchSameReturn`
|
||||
e) Triggerować `loadExtras()` jeśli wszystkie wymagane pola wypełnione
|
||||
|
||||
3. Problem z timingiem: po ustawieniu segmentu, lokalizacje ładują się asynchronicznie. Rozwiązanie:
|
||||
- Dodać callback/promise lub event `carei:branches-loaded` który dispatch-uje się po załadowaniu lokalizacji
|
||||
- W prefill poczekać na ten event, potem ustawić pickupSelect.value
|
||||
|
||||
4. Osobna inicjalizacja dat w mini formularzu — labelki "Od kiedy?"/"Do kiedy?" zachowują się jak placeholdery (widoczne gdy puste).
|
||||
|
||||
Avoid:
|
||||
- Nie duplikować fetchowania API — jeśli dane już załadowane (dataLoaded=true), reużyć cache
|
||||
- Nie łamać istniejącej logiki modala — openModal() musi działać normalnie gdy wywoływana z przycisku `data-carei-open-modal`
|
||||
</action>
|
||||
<verify>Po wypełnieniu mini formularza i kliknięciu przycisku: modal się otwiera, pola segment/daty/lokalizacja są wypełnione, extras się ładują</verify>
|
||||
<done>AC-2, AC-3 satisfied: Selecty ładują dane, przycisk otwiera modal z pre-fill</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 3: CSS — stylowanie mini formularza zgodne z Figmą</name>
|
||||
<files>wp-content/plugins/carei-reservation/assets/css/carei-reservation.css</files>
|
||||
<action>
|
||||
Dodać style dla `.carei-search-form` na końcu pliku CSS:
|
||||
|
||||
1. Container `.carei-search-form`:
|
||||
- background: #EDEDF3
|
||||
- border-radius: 14px
|
||||
- border: 1px solid rgba(47, 36, 130, 0.1)
|
||||
- padding: ~24px 28px
|
||||
- max-width: 422px (z Figmy: width 422px)
|
||||
- box-shadow: subtletny drop shadow
|
||||
|
||||
2. Tytuł `.carei-search-form__title`:
|
||||
- font-family: 'Albert Sans', sans-serif
|
||||
- font-weight: 700
|
||||
- color: #2F2482
|
||||
- text-align: center
|
||||
- span (kropka): color: #FF0000
|
||||
|
||||
3. Pola formularza `.carei-search-form__field`:
|
||||
- background: #fff
|
||||
- border-radius: 8px
|
||||
- border: 1px solid #E0E0E0
|
||||
- padding: 12px 16px
|
||||
- font-size: 14px
|
||||
- Selecty: appearance: none + custom arrow icon
|
||||
- Daty: dwa pola obok siebie (flex row, gap)
|
||||
|
||||
4. Checkbox `.carei-search-form__checkbox`:
|
||||
- Styl jak w głównym formularzu (custom checkbox box z SVG checkmark)
|
||||
- Kolor checked: #2F2482
|
||||
|
||||
5. Przycisk `.carei-search-form__submit`:
|
||||
- background: #FF0000
|
||||
- color: #fff
|
||||
- border-radius: 8px
|
||||
- width: 100%
|
||||
- padding: 14px
|
||||
- font-weight: 600
|
||||
- ikona strzałki przed tekstem
|
||||
- hover: lekkie przyciemnienie
|
||||
|
||||
6. Responsive:
|
||||
- Na mobile (< 768px): max-width: 100%, padding zmniejszony
|
||||
- Pola dat: mogą być w kolumnie na bardzo wąskich ekranach (< 400px)
|
||||
|
||||
Avoid: Nie modyfikować istniejących styli modala/formularza — dodać TYLKO nowe reguły z prefiksem `.carei-search-form`
|
||||
</action>
|
||||
<verify>Mini formularz wygląda zgodnie z designem z Figmy: tło szare, pola białe, przycisk czerwony, tytuł fioletowy</verify>
|
||||
<done>AC-4 satisfied: Design zgodny z Figmą</done>
|
||||
</task>
|
||||
|
||||
<task type="checkpoint:human-verify" gate="blocking">
|
||||
<what-built>Mini formularz rezerwacji w hero z pre-fill do modala</what-built>
|
||||
<how-to-verify>
|
||||
1. Otwórz stronę w Elementorze, osadź widget "Carei Search Form" w sekcji hero
|
||||
2. Na tej samej stronie musi być osadzony widget "Carei Reservation" (renderuje modal)
|
||||
3. Podgląd strony:
|
||||
- Mini formularz widoczny z polami segment, daty, lokalizacja, checkbox
|
||||
- Wybierz segment → lokalizacje się filtrują
|
||||
- Wypełnij daty i lokalizację
|
||||
- Kliknij "Złóż zapytanie o rezerwację"
|
||||
- Modal się otwiera z wypełnionymi danymi
|
||||
- Extras ładują się automatycznie
|
||||
4. Sprawdź design: tło szare, pola białe, przycisk czerwony
|
||||
5. Sprawdź mobile: formularz responsywny
|
||||
</how-to-verify>
|
||||
<resume-signal>Type "approved" to continue, or describe issues to fix</resume-signal>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<boundaries>
|
||||
|
||||
## DO NOT CHANGE
|
||||
- includes/class-elementor-widget.php — HTML modala pozostaje bez zmian
|
||||
- includes/class-softra-api.php — logika API bez zmian
|
||||
- includes/class-rest-proxy.php — endpointy REST bez zmian
|
||||
- includes/class-admin-panel.php — panel admina bez zmian
|
||||
|
||||
## SCOPE LIMITS
|
||||
- Mini formularz NIE ma własnego modala — korzysta z modala renderowanego przez istniejący widget
|
||||
- Brak walidacji w mini formularzu — walidacja jest w głównym formularzu
|
||||
- Brak pól danych osobowych w mini formularzu — tylko dane wynajmu
|
||||
- Nie dodawać nowych zależności npm/composer
|
||||
|
||||
</boundaries>
|
||||
|
||||
<verification>
|
||||
Before declaring plan complete:
|
||||
- [ ] Widget "Carei Search Form" widoczny w panelu Elementor
|
||||
- [ ] Mini formularz renderuje się na stronie z prawidłowym designem
|
||||
- [ ] Selecty segmentu i lokalizacji ładują dane z API
|
||||
- [ ] Kliknięcie przycisku otwiera modal z pre-wypełnionymi danymi
|
||||
- [ ] Istniejący przycisk `data-carei-open-modal` nadal działa normalnie
|
||||
- [ ] Responsive: formularz poprawny na mobile
|
||||
- [ ] Brak błędów JS w konsoli
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- Widget osadzony w Elementorze renderuje mini formularz
|
||||
- Dane z mini formularza poprawnie przenoszone do modala
|
||||
- Design zgodny z Figmą
|
||||
- Istniejąca funkcjonalność modala nienaruszona
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.paul/phases/07-hero-search-form/07-01-SUMMARY.md`
|
||||
</output>
|
||||
122
.paul/phases/07-hero-search-form/07-01-SUMMARY.md
Normal file
122
.paul/phases/07-hero-search-form/07-01-SUMMARY.md
Normal file
@@ -0,0 +1,122 @@
|
||||
---
|
||||
phase: 07-hero-search-form
|
||||
plan: 01
|
||||
subsystem: ui
|
||||
tags: [elementor, widget, vanilla-js, css]
|
||||
|
||||
requires:
|
||||
- phase: 01-reservation-form-plugin
|
||||
provides: plugin bootstrap, API proxy, Elementor widget infrastructure
|
||||
- phase: 02-form-ui-step1
|
||||
provides: modal form UI, segments/branches data loading
|
||||
provides:
|
||||
- Carei Search Form Elementor widget (mini formularz hero)
|
||||
- Pre-fill modal z danymi z mini formularza
|
||||
affects: []
|
||||
|
||||
tech-stack:
|
||||
added: []
|
||||
patterns: [search-form-prefill-via-setTimeout-polling]
|
||||
|
||||
key-files:
|
||||
created:
|
||||
- wp-content/plugins/carei-reservation/includes/class-search-widget.php
|
||||
modified:
|
||||
- wp-content/plugins/carei-reservation/carei-reservation.php
|
||||
- wp-content/plugins/carei-reservation/assets/js/carei-reservation.js
|
||||
- wp-content/plugins/carei-reservation/assets/css/carei-reservation.css
|
||||
|
||||
key-decisions:
|
||||
- "Calendar picker: opacity:0 stretched over input instead of display:none — preserves native click-to-open"
|
||||
- "Search form loads API data independently — not dependent on modal being present"
|
||||
|
||||
patterns-established:
|
||||
- "Mini form prefill: collect values → openModal() → setTimeout prefill → poll for async-loaded options"
|
||||
|
||||
duration: ~30min
|
||||
started: 2026-04-01T13:00:00Z
|
||||
completed: 2026-04-01T13:45:00Z
|
||||
---
|
||||
|
||||
# Phase 7 Plan 01: Hero Search Form Summary
|
||||
|
||||
**Kompaktowy widget Elementor "Carei Search Form" w hero z pre-fill do istniejącego modala rezerwacji**
|
||||
|
||||
## Performance
|
||||
|
||||
| Metric | Value |
|
||||
|--------|-------|
|
||||
| Duration | ~30min |
|
||||
| Tasks | 4 completed (3 auto + 1 checkpoint) |
|
||||
| Files modified | 4 (1 created, 3 modified) |
|
||||
|
||||
## Acceptance Criteria Results
|
||||
|
||||
| Criterion | Status | Notes |
|
||||
|-----------|--------|-------|
|
||||
| AC-1: Widget renderuje mini formularz | Pass | Segment, daty, lokalizacja, checkbox, przycisk |
|
||||
| AC-2: Selecty ładują dane z API | Pass | Segmenty i lokalizacje filtrowane po segmencie |
|
||||
| AC-3: Przycisk otwiera modal z pre-fill | Pass | Segment, daty, lokalizacja przenoszone do modala |
|
||||
| AC-4: Design zgodny z Figmą | Pass | Tło #EDEDF3, pola białe, przycisk czerwony, tytuł fioletowy |
|
||||
|
||||
## Accomplishments
|
||||
|
||||
- Nowy widget Elementor "Carei Search Form" do osadzenia w hero
|
||||
- Pola mini formularza automatycznie przenoszone do modala rezerwacji po kliknięciu przycisku
|
||||
- Niezależne ładowanie danych API (nie wymaga wcześniejszego otwarcia modala)
|
||||
|
||||
## Files Created/Modified
|
||||
|
||||
| File | Change | Purpose |
|
||||
|------|--------|---------|
|
||||
| `includes/class-search-widget.php` | Created | Widget Elementor z HTML mini formularza |
|
||||
| `carei-reservation.php` | Modified | Rejestracja nowego widgetu |
|
||||
| `assets/js/carei-reservation.js` | Modified | initSearchForm() — ładowanie danych, prefill, otwarcie modala |
|
||||
| `assets/css/carei-reservation.css` | Modified | Style .carei-search-form (tło, pola, przycisk, responsive) |
|
||||
|
||||
## Decisions Made
|
||||
|
||||
| Decision | Rationale | Impact |
|
||||
|----------|-----------|--------|
|
||||
| Osobne ładowanie API w search form | Niezależność od modala — dane dostępne od razu po załadowaniu strony | Dwa requesty API przy page load (zamiast lazy) |
|
||||
| Polling na pickup options po prefill | Lokalizacje ładują się async po zmianie segmentu — nie ma eventa | setInterval z max 30 prób (3s timeout) |
|
||||
|
||||
## Deviations from Plan
|
||||
|
||||
### Summary
|
||||
|
||||
| Type | Count | Impact |
|
||||
|------|-------|--------|
|
||||
| Auto-fixed | 1 | Niezbędny fix CSS |
|
||||
|
||||
**Total impact:** Fix CSS kalendarza — konieczny dla UX
|
||||
|
||||
### Auto-fixed Issues
|
||||
|
||||
**1. CSS calendar picker indicator**
|
||||
- **Found during:** Checkpoint (human-verify)
|
||||
- **Issue:** `display:none` na ikonkach kalendarza blokowało otwarcie date picker
|
||||
- **Fix:** Zmiana na `opacity:0` + stretch na cały input (wzorzec z głównego formularza)
|
||||
- **Files:** carei-reservation.css
|
||||
- **Verification:** Kliknięcie w pole daty otwiera picker
|
||||
|
||||
**2. CSS datetime placeholder selectable**
|
||||
- **Found during:** Checkpoint (human-verify)
|
||||
- **Issue:** Placeholder "--" w pustych polach dat był zaznaczalny
|
||||
- **Fix:** Dodanie `user-select:none` + `color:transparent` na `::-webkit-datetime-edit`
|
||||
- **Verification:** Placeholder niewidoczny i niezaznaczalny
|
||||
|
||||
## Next Phase Readiness
|
||||
|
||||
**Ready:**
|
||||
- Mini formularz działa i jest osadzony w hero
|
||||
- Modal rezerwacji przyjmuje pre-fill z zewnętrznego źródła
|
||||
|
||||
**Concerns:**
|
||||
- Dwa niezależne requesty API (search form + modal) — mogą powodować podwójne obciążenie przy jednoczesnym ładowaniu
|
||||
|
||||
**Blockers:** None
|
||||
|
||||
---
|
||||
*Phase: 07-hero-search-form, Plan: 01*
|
||||
*Completed: 2026-04-01*
|
||||
Reference in New Issue
Block a user