This commit is contained in:
2026-03-30 20:23:04 +02:00
parent df13b3613c
commit ca8db7a9da
23 changed files with 972 additions and 108 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -44,7 +44,6 @@ Plugin Elementor do rezerwacji samochodu na stronie carei.pagedev.pl, zintegrowa
## Out of Scope (backlog)
- Ubezpieczenie (pakiet Soft/Premium) — czeka na API Softra
- Wyjazd zagraniczny (lista krajów + ceny) — czeka na API Softra
- Eksport CSV/PDF rezerwacji
- Email notyfikacje

View File

@@ -19,6 +19,18 @@ Edge cases (token retry, timeout, network errors), animacje przejść form↔sum
### Phase 5: Admin Panel — Historia Formularzy ✅ Complete
CPT `carei_reservation` z automatycznym zapisem po booking, lista z kolumnami i filtrem statusu, meta box szczegółów, system statusów nowe/przeczytane/zrealizowane, auto-mark-read.
---
## Milestone v0.2: Wyjazd Zagraniczny
**Goal:** Wydzielenie pozycji "WYJAZD ZA GRANICĘ" z opcji dodatkowych do dedykowanej sekcji z wyszukiwarką krajów (zgodnie z Figmą).
**Status:** In progress
### Phase 6: Wyjazd zagraniczny — sekcja + wyszukiwarka krajów 🔄 Planning
Sekcja "Wyjazd zagraniczny" z checkboxem toggle, wyszukiwarką krajów z flagami/cenami, dodawanie/usuwanie krajów, integracja z API submit. Design z Figmy (node 32-397, 122:1054, 122:1091, 123:1195).
---
### Backlog (do realizacji gdy API będzie gotowe)
- **Wyjazd zagraniczny:** Checkbox "Planuję trasę poza granicę Polski" + wyszukiwarka krajów z cenami. Wymaga endpointu listy krajów i cennika per kraj w API Softra.
- **Ubezpieczenie:** Sekcja "Pakiet ochrony Soft/Premium" jak na Figmie. Wymaga dedykowanych pozycji ubezpieczeniowych w API pricelist.

View File

@@ -2,35 +2,33 @@
## Current Position
Milestone: v0.1 Formularz Rezerwacji MVP — COMPLETE
Phase: 5 of 5 (Admin Panel — Historia Formularzy) — Complete
Plan: 05-01 — Complete
Status: Milestone v0.1 complete — all 5 phases finished
Last activity: 2026-03-25Phase 5 unified, milestone complete
Milestone: v0.2 Wyjazd Zagraniczny
Phase: 6 of 6 (Wyjazd zagraniczny — sekcja + wyszukiwarka krajów) — Planning
Plan: 06-01 created, awaiting approval
Status: PLAN created, ready for APPLY
Last activity: 2026-03-30Created .paul/phases/06-wyjazd-zagraniczny/06-01-PLAN.md
Progress:
- Milestone: [██████████] 100% ✅
- Phase 1: [██████████] 100% ✅
- Phase 2: [██████████] 100% ✅
- Phase 3: [██████████] 100% ✅
- Phase 4: [██████████] 100% ✅
- Phase 5: [██████████] 100% ✅
- Milestone v0.1: [██████████] 100% ✅
- Milestone v0.2: [░░░░░░░░░░] 0%
- Phase 6: [░░░░░░░░░░] 0%
## Loop Position
Current loop state:
```
PLAN ──▶ APPLY ──▶ UNIFY
[Loop complete — milestone v0.1 finished]
[Plan created, awaiting approval]
```
## Session Continuity
Last session: 2026-03-25
Stopped at: Milestone v0.1 complete — all phases unified
Next action: /paul:complete-milestone or start next milestone
Resume file: .paul/ROADMAP.md
Last session: 2026-03-30
Stopped at: Plan 06-01 created
Next action: Review and approve plan, then run /paul:apply .paul/phases/06-wyjazd-zagraniczny/06-01-PLAN.md
Resume file: .paul/phases/06-wyjazd-zagraniczny/06-01-PLAN.md
Resume context:
- All 5 phases complete: skeleton, form UI, booking flow, polish, admin panel
- Plugin fully functional: formularz → API Softra → admin panel
- Backlog: ubezpieczenie + wyjazd zagraniczny (czeka na API)
- v0.1 complete (5 phases)
- v0.2 Phase 6: wyjazd zagraniczny — wydzielenie WYJAZD ZA GRANICĘ z extras do dedykowanej sekcji z wyszukiwarką krajów
- Dane krajów z istniejącego pricelist API (additionalItems z nazwą WYJAZD ZA GRANIC...)
- Design z Figmy: checkbox toggle + wyszukiwarka z flagami/cenami + karty krajów

View File

@@ -0,0 +1,282 @@
---
phase: 06-wyjazd-zagraniczny
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
- 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
autonomous: false
---
<objective>
## Goal
Wydzielić pozycje "WYJAZD ZA GRANICĘ ..." z sekcji "Opcje dodatkowe" do osobnej sekcji "Wyjazd zagraniczny" z checkboxem "Planuję trasę poza granicę Polski" i interaktywną wyszukiwarką krajów zgodną z Figmą.
## Purpose
Użytkownik chcący zarezerwować samochód z wyjazdem za granicę powinien mieć dedykowaną, intuicyjną sekcję zamiast listy checkboxów zagubionych wśród opcji dodatkowych. Design Figmy przewiduje wyszukiwarkę krajów z flagami, cenami i możliwością dodawania/usuwania — lepsze UX niż surowe checkboxy.
## Output
- Sekcja "Wyjazd zagraniczny" z checkboxem toggle
- Wyszukiwarka krajów z 3 stanami (default, active, z wybranymi)
- Karty krajów z flagą, nazwą, ceną, przyciskiem +/×
- Wybrane kraje trafiają do API jako extras przy submit
</objective>
<context>
## Project Context
@.paul/PROJECT.md
@.paul/ROADMAP.md
@.paul/STATE.md
## Prior Work
@.paul/phases/02-form-ui/02-01-SUMMARY.md — struktura formularza (opcje dodatkowe, loadExtras)
## Source Files
@wp-content/plugins/carei-reservation/includes/class-elementor-widget.php — HTML formularza (linia 126-143: extras wrapper)
@wp-content/plugins/carei-reservation/assets/js/carei-reservation.js — loadExtras() linia 315-346, buildExtraCard() linia 348-364, getSelectedExtrasForApi() linia 588-604
@wp-content/plugins/carei-reservation/assets/css/carei-reservation.css — style extra-card (linia 390-429)
## Design Reference
@docs/figma-formularz/README.md — sekcja "Wyjazd zagraniczny" (linia 113-117) + wyszukiwarka krajów (linia 146-177)
@docs/figma-formularz/input-wyszukiwarka-krajow.jsx — stany wyszukiwarki, karty krajów, kolory
@docs/figma-formularz/screenshot-popup-desktop.png
@docs/figma-formularz/screenshot-input-kraje-stany.png
</context>
<skills>
No SPECIAL-FLOWS.md — skills section omitted.
</skills>
<acceptance_criteria>
## AC-1: Pozycje WYJAZD ZA GRANICĘ nie pojawiają się w Opcjach dodatkowych
```gherkin
Given formularz z załadowanym cennikiem z API
When pricelist zawiera pozycje zaczynające się od "WYJAZD ZA GRANIC"
Then te pozycje NIE wyświetlają się w sekcji "Opcje dodatkowe"
And wyświetlają się TYLKO w sekcji "Wyjazd zagraniczny"
```
## AC-2: Sekcja "Wyjazd zagraniczny" z checkboxem toggle
```gherkin
Given formularz z załadowanymi extras
When użytkownik widzi sekcję "Wyjazd zagraniczny"
Then widoczny jest checkbox "Planuję trasę poza granicę Polski"
And wyszukiwarka krajów jest UKRYTA dopóki checkbox nie jest zaznaczony
When użytkownik zaznacza checkbox
Then wyszukiwarka krajów pojawia się z animacją
When użytkownik odznacza checkbox
Then wyszukiwarka znika i wybrane kraje się czyszczą
```
## AC-3: Wyszukiwarka krajów — wyszukiwanie i dodawanie
```gherkin
Given checkbox "Planuję trasę..." jest zaznaczony
When użytkownik widzi domyślny stan wyszukiwarki
Then widzi ikonę "+" i tekst "Wyszukaj i dodaj kraj na trasie"
When użytkownik klika pole i wpisuje tekst (np. "Nie")
Then pod polem pojawiają się karty krajów pasujących do frazy
And każda karta ma: flagę (emoji/obraz), nazwę kraju, cenę "od X do Y zł", przycisk "+"
When użytkownik klika "+" na karcie kraju
Then kraj zostaje dodany do listy wybranych (karta zmienia styl na selected, "+" "×")
```
## AC-4: Wybrane kraje trafiają do API przy submit
```gherkin
Given użytkownik wybrał kraje w wyszukiwarce (np. Niemcy, Czechy)
When formularz jest submitowany
Then getSelectedExtrasForApi() zawiera pozycje z pricelist odpowiadające wybranym krajom
And pricing summary i booking zawierają te pozycje
```
## AC-5: Design zgodny z Figmą
```gherkin
Given sekcja "Wyjazd zagraniczny" jest wyświetlona
Then separator "Wyjazd zagraniczny" ma taki sam styl jak inne separatory
And karty krajów mają: border-radius 8px, nazwę w #2F2482 Albert Sans SemiBold 15px, cenę w #505050
And wybrany kraj ma tło rgba(47,36,130,0.05), border rgba(47,36,130,0.2)
And pole wyszukiwarki ma 48px wysokości, border-radius 8px
```
</acceptance_criteria>
<tasks>
<task type="auto">
<name>Task 1: HTML sekcji "Wyjazd zagraniczny" + filtrowanie w JS</name>
<files>wp-content/plugins/carei-reservation/includes/class-elementor-widget.php, wp-content/plugins/carei-reservation/assets/js/carei-reservation.js</files>
<action>
**PHP (class-elementor-widget.php):**
Dodać nową sekcję HTML PRZED sekcją "Opcje dodatkowe" (między linią 135 "Ubezpieczenie" a linią 136 "Opcje dodatkowe"):
```
<div class="carei-form__divider"><span>Wyjazd zagraniczny</span></div>
<div class="carei-form__section" id="carei-abroad-section">
<label class="carei-form__checkbox-label">
<input type="checkbox" id="carei-abroad-toggle" name="abroadToggle">
<span class="carei-form__checkbox-box"><svg ...checkmark...</svg></span>
<span>Planuję trasę poza granicę Polski</span>
</label>
<div id="carei-abroad-search" class="carei-abroad" style="display:none;">
<div class="carei-abroad__input-wrap" id="carei-abroad-input-wrap">
<svg class="carei-abroad__plus-icon">+</svg>
<input type="text" id="carei-abroad-input" class="carei-abroad__input" placeholder="Wyszukaj i dodaj kraj na trasie">
</div>
<div class="carei-abroad__results" id="carei-abroad-results"></div>
<div class="carei-abroad__selected" id="carei-abroad-selected"></div>
</div>
</div>
```
**JS (carei-reservation.js) — modyfikacja loadExtras():**
W pętli `items.forEach()` (linia 329-341) dodać trzecią kategorię:
- Jeśli `name` zaczyna się od "wyjazd za granic" → `abroadItems.push(item)` (NIE do extraItems)
- Parsować nazwę kraju z item.name (np. "WYJAZD ZA GRANICĘ - NIEMCY" → "Niemcy")
- Przechowywać `abroadItems` w zmiennej modułowej (dostępnej dla wyszukiwarki)
Po załadowaniu — NIE renderować abroadItems jako checkboxów. Zamiast tego, zachować dane w pamięci JS do użycia przez wyszukiwarkę.
Avoid: Nie usuwać istniejącej logiki insurance/extras — tylko dodać nową kategorię w `forEach`.
</action>
<verify>
1. Otworzyć formularz, wybrać segment i oddział
2. Pozycje "WYJAZD ZA GRANICĘ ..." NIE pojawiają się w "Opcje dodatkowe"
3. Widoczna sekcja "Wyjazd zagraniczny" z checkboxem
</verify>
<done>AC-1 satisfied: pozycje WYJAZD nie lądują w Opcjach dodatkowych. AC-2 partially: sekcja HTML istnieje.</done>
</task>
<task type="auto">
<name>Task 2: Wyszukiwarka krajów — interakcje JS + style CSS</name>
<files>wp-content/plugins/carei-reservation/assets/js/carei-reservation.js, wp-content/plugins/carei-reservation/assets/css/carei-reservation.css</files>
<action>
**JS — nowy blok "Abroad Country Search":**
1. **Toggle checkbox:** Listener na `#carei-abroad-toggle`:
- checked → `#carei-abroad-search` display:block (slide down)
- unchecked → hide + wyczyść selected countries
2. **Mapowanie krajów na flagi:** Obiekt `COUNTRY_FLAGS` z emoji flagami dla typowych krajów (Niemcy 🇩🇪, Czechy 🇨🇿, Norwegia 🇳🇴, etc.). Fallback: flaga 🏳️.
3. **Wyszukiwanie:** Input event na `#carei-abroad-input`:
- Filtruj `abroadItems` po nazwie kraju (case-insensitive, includes)
- Renderuj karty wyników w `#carei-abroad-results` (2 kolumny CSS grid)
- Karta: flaga (emoji 24px) + nazwa kraju + cena "od X do Y zł" + przycisk "+"
- Już wybrane kraje w wynikach → styl selected (bg/border Figma) + przycisk "×"
- Puste pole = nie pokazuj wyników (stan default)
4. **Dodawanie kraju ("+"):**
- Dodaj do `selectedCountries` Map (id → item)
- Przerenderuj wyniki (kraj zmienia się na selected)
- Przerenderuj `#carei-abroad-selected` — lista wybranych pod wyszukiwarką
5. **Usuwanie kraju ("×"):**
- Usuń z `selectedCountries`
- Przerenderuj wyniki i selected
6. **Integracja z getSelectedExtrasForApi():**
Zmodyfikować `getSelectedExtrasForApi()` (linia 588-604) — oprócz `extras[]` checkboxów, dołączyć kraje z `selectedCountries` Map w tym samym formacie:
```js
selectedCountries.forEach(function(item) {
items.push({ id: item.id || item.code, name: item.name, ... });
});
```
**CSS — nowe reguły `.carei-abroad`:**
Zgodne z Figmą (docs/figma-formularz):
- `.carei-abroad__input-wrap`: height 48px, border-radius 8px, border 1px #D0D0D0, flex, gap 8px, padding 0 16px, align-items center
- `.carei-abroad__input`: no border, flex 1, Albert Sans SemiBold 15px, color #2F2482, placeholder color #C7C7C7
- `.carei-abroad__plus-icon`: 16px, color #2F2482
- `.carei-abroad__results`: display grid, grid-template-columns 1fr 1fr, gap 8px, margin-top 8px
- `.carei-abroad__card`: height 56px, border-radius 8px, border 1px rgba(0,0,0,0.1), flex, align-items center, padding 0 12px, gap 8px
- `.carei-abroad__card--selected`: background rgba(47,36,130,0.05), border-color rgba(47,36,130,0.2)
- `.carei-abroad__flag`: width 24px, height 24px, border-radius 50%, font-size 20px, line-height 24px, text-align center
- `.carei-abroad__name`: Albert Sans SemiBold 15px, color #2F2482, flex 1
- `.carei-abroad__price`: text-align right, color #505050 (format: "od" 10px + wartość 14px + "do" 10px + wartość 14px + "zł")
- `.carei-abroad__action`: 16px button, cursor pointer, no bg/border
- `.carei-abroad__selected`: margin-top 8px, flex column, gap 8px
Mobile (max-width 600px):
- `.carei-abroad__results`: grid-template-columns 1fr (1 kolumna)
Avoid: Nie modyfikować istniejących stylów `.carei-form__extra-card`. Nowe klasy `.carei-abroad__*`.
</action>
<verify>
1. Zaznacz checkbox "Planuję trasę..." → wyszukiwarka się pojawia
2. Wpisz "Niem" → pojawia się karta Niemcy z flagą, ceną, "+"
3. Kliknij "+" → Niemcy zmienia styl na selected, pojawia się w liście wybranych z "×"
4. Kliknij "×" → kraj usunięty
5. Odznacz checkbox → wyszukiwarka znika, wybrane kraje się czyszczą
6. Submit z wybranym krajem → pricing summary zawiera pozycję WYJAZD
</verify>
<done>AC-2, AC-3, AC-4, AC-5 satisfied: pełna interakcja wyszukiwarki, integracja z API, design Figma</done>
</task>
<task type="checkpoint:human-verify" gate="blocking">
<what-built>Sekcja "Wyjazd zagraniczny" z wyszukiwarką krajów w popup rezerwacji</what-built>
<how-to-verify>
1. Otwórz stronę z formularzem rezerwacji
2. Wybierz segment i oddział (żeby załadować extras)
3. Sprawdź: pozycje "WYJAZD ZA GRANICĘ ..." NIE widać w "Opcje dodatkowe"
4. Sprawdź: widoczna sekcja "Wyjazd zagraniczny" z checkboxem
5. Zaznacz "Planuję trasę poza granicę Polski" → wyszukiwarka się pojawia
6. Wpisz fragment nazwy kraju → karty z flagami i cenami
7. Dodaj kraj (+) → karta się podświetla, pojawia się w liście wybranych
8. Usuń kraj (×) → znika z wybranych
9. Odznacz checkbox → wszystko się czyści
10. Zaznacz, dodaj kraje, submit → w summary widać pozycje WYJAZD
11. Sprawdź responsywność na mobile (1 kolumna kart)
12. Porównaj wygląd z Figmą (kolory, fonty, spacing)
</how-to-verify>
<resume-signal>Type "approved" to continue, or describe issues to fix</resume-signal>
</task>
</tasks>
<boundaries>
## DO NOT CHANGE
- wp-content/plugins/carei-reservation/includes/class-softra-api.php (API client — nie wymaga zmian)
- wp-content/plugins/carei-reservation/includes/class-rest-proxy.php (REST proxy — nie wymaga zmian)
- wp-content/plugins/carei-reservation/includes/class-admin-panel.php (Admin panel — osobna funkcjonalność)
- Istniejąca logika ubezpieczeń (filtrowanie ubezp/ochrony w loadExtras)
- Istniejąca logika buildExtraCard() — nie modyfikować, nowe karty mają osobny builder
- Istniejące style .carei-form__extra-card — nie modyfikować
## SCOPE LIMITS
- Nie dodawać prawdziwych obrazów flag (emoji wystarczą na MVP)
- Nie tworzyć osobnego API endpoint do krajów — dane z istniejącego pricelist
- Nie modyfikować logiki booking/confirm — tylko getSelectedExtrasForApi()
- Nie dodawać walidacji "minimum 1 kraj wybrany" — checkbox sam w sobie jest opcjonalny
- Summary overlay — wystarczy że kraje pojawią się jako standardowe pozycje extras
</boundaries>
<verification>
Before declaring plan complete:
- [ ] Pozycje "WYJAZD ZA GRANIC..." nie pojawiają się w "Opcje dodatkowe"
- [ ] Sekcja "Wyjazd zagraniczny" wyświetla się z separatorem i checkboxem
- [ ] Toggle checkbox pokazuje/ukrywa wyszukiwarkę
- [ ] Wyszukiwanie filtruje kraje w real-time
- [ ] Dodawanie/usuwanie krajów działa poprawnie
- [ ] Wybrane kraje trafiają do getSelectedExtrasForApi()
- [ ] Pricing summary zawiera pozycje WYJAZD dla wybranych krajów
- [ ] Mobile: karty w 1 kolumnie
- [ ] Brak błędów w konsoli JS
</verification>
<success_criteria>
- All tasks completed
- All verification checks pass
- No errors or warnings introduced
- Design wizualnie zgodny z Figmą (kolory, spacing, typografia)
- Istniejąca funkcjonalność (ubezpieczenie, opcje dodatkowe, booking flow) nienaruszona
</success_criteria>
<output>
After completion, create `.paul/phases/06-wyjazd-zagraniczny/06-01-SUMMARY.md`
</output>

View File

@@ -123,16 +123,22 @@
},
"handoffs": {
"archive": {
"HANDOFF-2026-03-25.md": {
"type": "-",
"size": 3911,
"lmtime": 1774394933000,
"modified": false
},
"HANDOFF-2026-03-25-phase3.md": {
"type": "-",
"size": 3672,
"lmtime": 1774440974369,
"modified": false
},
"HANDOFF-2026-03-25.md": {
"HANDOFF-2026-03-25-phase5.md": {
"type": "-",
"size": 3911,
"lmtime": 1774394933000,
"size": 4436,
"lmtime": 1774453504000,
"modified": false
}
}
@@ -181,25 +187,31 @@
"size": 11298,
"lmtime": 1774447717369,
"modified": false
},
"05-01-SUMMARY.md": {
"type": "-",
"size": 4697,
"lmtime": 1774456664870,
"modified": false
}
}
},
"PROJECT.md": {
"type": "-",
"size": 2025,
"lmtime": 0,
"size": 3246,
"lmtime": 1774456701930,
"modified": false
},
"ROADMAP.md": {
"type": "-",
"size": 1906,
"lmtime": 1774447405669,
"size": 1862,
"lmtime": 1774456710745,
"modified": false
},
"STATE.md": {
"type": "-",
"size": 1376,
"lmtime": 1774453515616,
"size": 1212,
"lmtime": 1774456724909,
"modified": false
}
},
@@ -301,8 +313,8 @@
"includes": {
"class-admin-panel.php": {
"type": "-",
"size": 18994,
"lmtime": 1774448051188,
"size": 19203,
"lmtime": 1774456454972,
"modified": false
},
"class-elementor-widget.php": {

11
.vscode/sftp.json vendored Normal file
View File

@@ -0,0 +1,11 @@
{
"name": "My Server",
"host": "localhost",
"protocol": "sftp",
"port": 22,
"username": "username",
"remotePath": "/",
"uploadOnSave": false,
"useTempFile": false,
"openSsh": false
}

BIN
wp-admin/.DS_Store vendored Normal file

Binary file not shown.

BIN
wp-content/.DS_Store vendored Normal file

Binary file not shown.

BIN
wp-content/languages/.DS_Store vendored Normal file

Binary file not shown.

BIN
wp-content/plugins/.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -77,6 +77,7 @@
width: 100%;
max-height: 90vh;
overflow-y: auto;
overflow-x: hidden;
padding: 40px 48px;
position: relative;
font-family: var(--carei-font);
@@ -93,13 +94,13 @@
background: none;
border: none;
cursor: pointer;
color: var(--carei-gray);
color: #B0B0B0;
line-height: 1;
padding: 4px;
transition: color 0.2s;
}
.carei-modal-close:hover {
color: var(--carei-blue);
color: #808080;
}
.carei-modal-title {
font-family: var(--carei-font);
@@ -140,7 +141,7 @@
}
.carei-form__row {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: var(--carei-gap-inner);
}
.carei-form__row--top {
@@ -217,6 +218,137 @@
color: var(--carei-gray);
}
/* Floating label for text inputs */
.carei-form__float-wrap {
position: relative;
height: var(--carei-input-h);
background: var(--carei-white);
border: 1px solid transparent;
border-radius: var(--carei-radius);
transition: border-color 0.2s;
}
.carei-form__float-wrap:focus-within {
border-color: var(--carei-blue);
}
.carei-form__float-label {
position: absolute;
left: 16px;
top: 50%;
transform: translateY(-50%);
font-family: var(--carei-font);
font-weight: 400;
font-size: 15px;
color: var(--carei-gray);
pointer-events: none;
transition: top 0.15s, font-size 0.15s, transform 0.15s;
z-index: 1;
}
.carei-form__float-label--static {
position: static;
transform: none;
font-size: 11px;
padding: 6px 16px 0;
display: block;
}
.carei-form__input--float {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border: none !important;
background: transparent !important;
padding: 0 16px !important;
z-index: 2;
}
.carei-form__input--float:not(:placeholder-shown) ~ .carei-form__float-label,
.carei-form__input--float:focus ~ .carei-form__float-label {
top: 8px;
transform: none;
font-size: 10px;
}
.carei-form__input--float:not(:placeholder-shown),
.carei-form__input--float:focus {
padding-top: 16px !important;
padding-bottom: 0 !important;
}
/* Date input with floating label */
.carei-form__date-wrap {
position: relative;
height: var(--carei-input-h);
background: var(--carei-white);
border: 1px solid transparent;
border-radius: var(--carei-radius);
transition: border-color 0.2s;
cursor: pointer;
}
.carei-form__date-wrap:focus-within {
border-color: var(--carei-blue);
}
.carei-form__date-icon {
position: absolute;
left: 12px;
top: 50%;
transform: translateY(-50%);
color: var(--carei-blue);
pointer-events: none;
z-index: 3;
}
.carei-form__date-label {
position: absolute;
left: 36px;
top: 50%;
transform: translateY(-50%);
font-family: var(--carei-font);
font-weight: 400;
font-size: 15px;
color: var(--carei-gray);
pointer-events: none;
transition: top 0.15s, font-size 0.15s, transform 0.15s;
z-index: 3;
}
.carei-form__date-wrap.has-value .carei-form__date-label {
top: 7px;
transform: none;
font-size: 10px;
}
.carei-form__input--date {
border: none !important;
background: transparent !important;
height: 100% !important;
width: 100%;
padding: 0 12px 0 36px !important;
font-size: 14px;
position: relative;
z-index: 2;
}
/* Pusty: ukryj natywny tekst i zablokuj interakcję z polami wewnętrznymi */
.carei-form__input--date.is-empty {
color: transparent !important;
z-index: 1;
}
.carei-form__input--date.is-empty::-webkit-datetime-edit {
color: transparent;
-webkit-user-select: none;
user-select: none;
}
/* Wypełniony: przesuń wartość w dół pod label */
.carei-form__date-wrap.has-value .carei-form__input--date {
padding-top: 14px !important;
padding-bottom: 0 !important;
}
/* Ukryj natywną ikonę kalendarza przeglądarki */
.carei-form__input--date::-webkit-calendar-picker-indicator {
opacity: 0;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
cursor: pointer;
}
/* Select wrapper */
.carei-form__select-wrap {
position: relative;
@@ -263,16 +395,30 @@
═══════════════════════════════════════════ */
.carei-form__phone-wrap {
display: flex;
align-items: center;
flex-direction: column;
background: var(--carei-white);
border-radius: var(--carei-radius);
border: 1px solid transparent;
transition: border-color 0.2s;
height: var(--carei-input-h);
padding: 4px 0 0;
}
.carei-form__phone-wrap:focus-within {
border-color: var(--carei-blue);
}
.carei-form__phone-label {
font-family: var(--carei-font);
font-weight: 400;
font-size: 10px;
color: var(--carei-gray);
padding: 0 16px;
line-height: 1;
}
.carei-form__phone-row {
display: flex;
align-items: center;
flex: 1;
}
.carei-form__phone-prefix {
display: flex;
align-items: center;
@@ -295,8 +441,10 @@
color: var(--carei-gray);
}
.carei-form__input--phone {
border: none;
background: transparent;
border: none !important;
background: transparent !important;
box-shadow: none !important;
outline: none !important;
height: 100%;
padding-left: 12px;
}
@@ -305,7 +453,7 @@
letter-spacing: 2px;
}
.carei-form__input--phone:focus {
border: none;
border: none !important;
}
/* ═══════════════════════════════════════════
@@ -397,35 +545,205 @@
padding: 16px;
background: var(--carei-white);
transition: border-color 0.2s;
min-width: 0;
overflow: hidden;
}
.carei-form__extra-card:has(input:checked) {
border-color: var(--carei-blue);
}
.carei-form__checkbox-label--card {
align-items: flex-start;
align-items: center;
}
.carei-form__extra-content {
display: flex;
flex-direction: column;
gap: 4px;
align-items: center;
gap: 8px;
flex: 1;
min-width: 0;
overflow: hidden;
}
.carei-form__extra-content strong {
font-weight: 700;
font-size: 14px;
font-weight: 600;
font-size: 15px;
color: var(--carei-blue);
word-break: break-word;
min-width: 0;
}
.carei-form__extra-desc {
font-size: 12px;
color: var(--carei-gray);
font-weight: 400;
line-height: 1.4;
display: none;
}
.carei-form__extra-price {
font-weight: 700;
font-weight: 400;
font-size: 14px;
color: var(--carei-gray);
margin-left: auto;
white-space: nowrap;
flex-shrink: 0;
}
.carei-form__checkbox-label--abroad {
align-items: center;
font-weight: 600;
font-size: 15px;
color: var(--carei-red);
margin-top: 4px;
}
/* ═══════════════════════════════════════════
Abroad Country Search
═══════════════════════════════════════════ */
.carei-abroad {
margin-top: 16px;
}
.carei-abroad__input-wrap {
display: flex;
align-items: center;
gap: 8px;
height: 48px;
padding: 0 16px;
border: 1px solid var(--carei-border);
border-radius: var(--carei-radius);
background: var(--carei-white);
transition: border-color 0.2s;
}
.carei-abroad__input-wrap:focus-within {
border-color: var(--carei-blue);
}
.carei-abroad__plus-icon {
flex-shrink: 0;
color: var(--carei-blue);
}
.carei-abroad__input {
flex: 1;
border: none !important;
outline: none !important;
box-shadow: none !important;
background: transparent !important;
font-family: 'Albert Sans', sans-serif;
font-weight: 600;
font-size: 15px;
color: var(--carei-blue);
line-height: 48px;
padding: 0 !important;
margin: 0;
min-width: 0;
}
.carei-abroad__input::placeholder {
font-weight: 400;
color: #C7C7C7;
}
.carei-abroad__clear {
display: none;
align-items: center;
justify-content: center;
flex-shrink: 0;
width: 20px;
height: 20px;
cursor: pointer;
color: #B0B0B0;
border-radius: 50%;
transition: color 0.15s;
}
.carei-abroad__clear:hover {
color: var(--carei-gray);
}
.carei-abroad__input-wrap.has-text .carei-abroad__clear {
display: flex;
}
.carei-abroad__results {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 8px;
margin-top: 8px;
}
.carei-abroad__results:empty {
display: none;
}
.carei-abroad__selected {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 8px;
margin-top: 8px;
}
.carei-abroad__selected:empty {
display: none;
}
.carei-abroad__card {
display: flex;
align-items: center;
gap: 8px;
height: 56px;
padding: 0 12px;
border: 1px solid rgba(0, 0, 0, 0.1);
border-radius: var(--carei-radius);
background: var(--carei-white);
transition: background-color 0.2s, border-color 0.2s;
min-width: 0;
overflow: hidden;
}
.carei-abroad__card:hover {
background: #2F24820D;
}
.carei-abroad__card--selected,
.carei-abroad__card--selected:hover {
background: rgba(47, 36, 130, 0.05);
border-color: rgba(47, 36, 130, 0.2);
}
.carei-abroad__flag {
flex-shrink: 0;
width: 24px;
height: 24px;
font-size: 20px;
line-height: 24px;
text-align: center;
}
.carei-abroad__name {
flex: 1;
font-family: 'Albert Sans', sans-serif;
font-weight: 600;
font-size: 15px;
color: var(--carei-blue);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.carei-abroad__price {
text-align: right;
color: #505050;
white-space: nowrap;
flex-shrink: 0;
}
.carei-abroad__price-small {
font-size: 10px;
}
.carei-abroad__price-val {
font-size: 14px;
}
.carei-abroad__action {
flex-shrink: 0;
width: 24px;
height: 24px;
display: flex;
align-items: center;
justify-content: center;
border: none !important;
background: transparent !important;
background-color: transparent !important;
cursor: pointer;
font-size: 18px;
font-weight: 700;
color: var(--carei-blue);
padding: 0;
line-height: 1;
border-radius: 50%;
-webkit-appearance: none;
appearance: none;
box-shadow: none;
}
@media (max-width: 600px) {
.carei-abroad__results,
.carei-abroad__selected {
grid-template-columns: 1fr;
}
}
/* ═══════════════════════════════════════════

View File

@@ -79,7 +79,7 @@
var overlay, form, segmentSelect, dateFrom, dateTo, daysCount;
var pickupSelect, returnSelect, returnWrap, sameReturnCheck;
var extrasWrapper, extrasContainer, insuranceContainer, errorSummary;
var extrasWrapper, extrasContainer, insuranceContainer, abroadSection, abroadToggle, abroadSearch, abroadInput, abroadResults, abroadSelected, errorSummary;
var summaryOverlay, summaryDetails, summaryTable, summaryTotal, summaryError;
var summaryBack, summaryConfirm;
var successView, successNumber, successClose;
@@ -98,6 +98,12 @@
extrasWrapper = document.getElementById('carei-extras-wrapper');
extrasContainer = document.getElementById('carei-extras-container');
insuranceContainer = document.getElementById('carei-insurance-container');
abroadSection = document.getElementById('carei-abroad-section');
abroadToggle = document.getElementById('carei-abroad-toggle');
abroadSearch = document.getElementById('carei-abroad-search');
abroadInput = document.getElementById('carei-abroad-input');
abroadResults = document.getElementById('carei-abroad-results');
abroadSelected = document.getElementById('carei-abroad-selected');
errorSummary = document.getElementById('carei-error-summary');
// Summary overlay
summaryOverlay = document.getElementById('carei-summary-overlay');
@@ -122,6 +128,8 @@
var currentReservationId = null;
var agreementDefs = [];
var lastFocusedElement = null;
var abroadItems = [];
var selectedCountries = {};
// ─── Modal Open/Close ─────────────────────────────────────────
@@ -155,7 +163,7 @@
document.body.style.overflow = 'hidden';
if (!dataLoaded) {
loadInitialData();
setDefaultDates();
initDateLabels();
dataLoaded = true;
}
setTimeout(function () {
@@ -276,30 +284,47 @@
function maybeShowExtras() {
var segment = segmentSelect ? segmentSelect.value : '';
var pickup = pickupSelect ? pickupSelect.value : '';
if (segment && pickup) { showExtras(); loadExtras(); } else { hideExtras(); }
var from = dateFrom ? dateFrom.value : '';
var to = dateTo ? dateTo.value : '';
if (segment && pickup && from && to) { showExtras(); loadExtras(); } else { hideExtras(); }
}
function showExtras() { if (extrasWrapper) extrasWrapper.style.display = ''; }
function hideExtras() { if (extrasWrapper) extrasWrapper.style.display = 'none'; }
// ─── Default Dates ────────────────────────────────────────────
// ─── Date Labels ──────────────────────────────────────────────
function setDefaultDates() {
if (!dateFrom || !dateTo) return;
var tomorrow = new Date(); tomorrow.setDate(tomorrow.getDate() + 1); tomorrow.setHours(10, 0, 0, 0);
var dayAfter = new Date(); dayAfter.setDate(dayAfter.getDate() + 2); dayAfter.setHours(10, 0, 0, 0);
dateFrom.value = fmtDT(tomorrow);
dateTo.value = fmtDT(dayAfter);
updateDaysCount();
function initDateLabels() {
[dateFrom, dateTo].forEach(function (input) {
if (!input) return;
updateDateEmpty(input);
input.addEventListener('change', function () { updateDateEmpty(input); updateDaysCount(); });
input.addEventListener('input', function () { updateDateEmpty(input); });
});
}
function fmtDT(d) {
return d.getFullYear() + '-' + pad(d.getMonth() + 1) + '-' + pad(d.getDate()) + 'T' + pad(d.getHours()) + ':' + pad(d.getMinutes());
function updateDateEmpty(input) {
var wrap = input.closest('.carei-form__date-wrap');
if (input.value) {
input.classList.remove('is-empty');
if (wrap) wrap.classList.add('has-value');
} else {
input.classList.add('is-empty');
if (wrap) wrap.classList.remove('has-value');
}
}
function pad(n) { return String(n).padStart(2, '0'); }
// ─── Days Count ───────────────────────────────────────────────
function getRentalDays() {
if (!dateFrom || !dateTo) return 1;
var from = new Date(dateFrom.value), to = new Date(dateTo.value);
if (isNaN(from.getTime()) || isNaN(to.getTime()) || to <= from) return 1;
return Math.ceil((to - from) / 86400000);
}
function updateDaysCount() {
if (!dateFrom || !dateTo || !daysCount) return;
var from = new Date(dateFrom.value), to = new Date(dateTo.value);
@@ -325,6 +350,8 @@
currentPriceListId = pricelist.id;
var items = pricelist.additionalItems;
var insuranceItems = [], extraItems = [];
abroadItems = [];
selectedCountries = {};
if (Array.isArray(items)) {
items.forEach(function (item) {
var name = (item.name || '').toLowerCase();
@@ -332,7 +359,11 @@
var code = (item.code || '').toUpperCase();
if (code.indexOf('BRAK') === 0 || code.indexOf('BRUD') === 0 || code.indexOf('KARA') === 0 ||
code.indexOf('MYCIE USŁU') === 0 || code === 'MYJ WEW') return;
if (name.indexOf('ubezp') !== -1 || name.indexOf('ochrony') !== -1 ||
if (name.indexOf('wyjazd za granic') !== -1) {
item._countryName = parseCountryName(item.name);
item._countryFlag = getCountryFlag(item._countryName);
abroadItems.push(item);
} else if (name.indexOf('ubezp') !== -1 || name.indexOf('ochrony') !== -1 ||
name.indexOf('zniesienie') !== -1 || name.indexOf('insurance') !== -1) {
insuranceItems.push(item);
} else {
@@ -342,6 +373,8 @@
}
if (insuranceContainer) { insuranceContainer.innerHTML = ''; insuranceItems.forEach(function (item) { insuranceContainer.appendChild(buildExtraCard(item)); }); }
if (extrasContainer) { extrasContainer.innerHTML = ''; extraItems.forEach(function (item) { extrasContainer.appendChild(buildExtraCard(item)); }); }
if (abroadSection) { abroadSection.style.display = abroadItems.length > 0 ? '' : 'none'; }
renderAbroadSelected();
}).catch(function (err) { console.error('Failed to load pricelist:', err); });
}
@@ -363,6 +396,147 @@
return card;
}
// ─── Abroad Country Search ─────────────────────────────────────
var COUNTRY_FLAGS = {
'niemcy': '\u{1F1E9}\u{1F1EA}', 'czechy': '\u{1F1E8}\u{1F1FF}', 'słowacja': '\u{1F1F8}\u{1F1F0}',
'austria': '\u{1F1E6}\u{1F1F9}', 'francja': '\u{1F1EB}\u{1F1F7}', 'włochy': '\u{1F1EE}\u{1F1F9}',
'hiszpania': '\u{1F1EA}\u{1F1F8}', 'holandia': '\u{1F1F3}\u{1F1F1}', 'belgia': '\u{1F1E7}\u{1F1EA}',
'dania': '\u{1F1E9}\u{1F1F0}', 'szwecja': '\u{1F1F8}\u{1F1EA}', 'norwegia': '\u{1F1F3}\u{1F1F4}',
'finlandia': '\u{1F1EB}\u{1F1EE}', 'szwajcaria': '\u{1F1E8}\u{1F1ED}', 'węgry': '\u{1F1ED}\u{1F1FA}',
'chorwacja': '\u{1F1ED}\u{1F1F7}', 'słowenia': '\u{1F1F8}\u{1F1EE}', 'litwa': '\u{1F1F1}\u{1F1F9}',
'łotwa': '\u{1F1F1}\u{1F1FB}', 'estonia': '\u{1F1EA}\u{1F1EA}', 'rumunia': '\u{1F1F7}\u{1F1F4}',
'bułgaria': '\u{1F1E7}\u{1F1EC}', 'portugalia': '\u{1F1F5}\u{1F1F9}', 'grecja': '\u{1F1EC}\u{1F1F7}',
'wielka brytania': '\u{1F1EC}\u{1F1E7}', 'irlandia': '\u{1F1EE}\u{1F1EA}', 'luksemburg': '\u{1F1F1}\u{1F1FA}',
'serbia': '\u{1F1F7}\u{1F1F8}', 'czarnogóra': '\u{1F1F2}\u{1F1EA}', 'albania': '\u{1F1E6}\u{1F1F1}',
'turcja': '\u{1F1F9}\u{1F1F7}', 'ukraina': '\u{1F1FA}\u{1F1E6}', 'mołdawia': '\u{1F1F2}\u{1F1E9}'
};
function parseCountryName(name) {
var raw = (name || '').replace(/wyjazd za granic[eę]\s*[-–—]?\s*/i, '').trim();
if (!raw) return name || '';
return raw.split(/\s+/).map(function (w) {
return w.charAt(0).toUpperCase() + w.slice(1).toLowerCase();
}).join(' ');
}
function getCountryFlag(countryName) {
var key = (countryName || '').toLowerCase();
return COUNTRY_FLAGS[key] || '\u{1F3F3}\u{FE0F}';
}
function initAbroad() {
if (!abroadToggle || !abroadSearch) return;
abroadToggle.addEventListener('change', function () {
if (abroadToggle.checked) {
abroadSearch.style.display = '';
} else {
abroadSearch.style.display = 'none';
selectedCountries = {};
if (abroadInput) abroadInput.value = '';
renderAbroadResults([]);
renderAbroadSelected();
}
});
var abroadClear = document.getElementById('carei-abroad-clear');
if (abroadInput) {
abroadInput.addEventListener('input', function () {
updateAbroadClear();
var query = abroadInput.value.trim().toLowerCase();
if (!query) { renderAbroadResults([]); return; }
var filtered = abroadItems.filter(function (item) {
return item._countryName.toLowerCase().indexOf(query) !== -1;
});
renderAbroadResults(filtered);
});
abroadInput.addEventListener('focus', function () {
var query = abroadInput.value.trim().toLowerCase();
if (query) {
var filtered = abroadItems.filter(function (item) {
return item._countryName.toLowerCase().indexOf(query) !== -1;
});
renderAbroadResults(filtered);
}
});
}
if (abroadClear) {
abroadClear.addEventListener('click', function () {
if (abroadInput) { abroadInput.value = ''; abroadInput.focus(); }
renderAbroadResults([]);
updateAbroadClear();
});
}
function updateAbroadClear() {
var wrap = abroadInput ? abroadInput.closest('.carei-abroad__input-wrap') : null;
if (wrap) {
if (abroadInput.value.trim()) { wrap.classList.add('has-text'); }
else { wrap.classList.remove('has-text'); }
}
}
}
function renderAbroadResults(items) {
if (!abroadResults) return;
abroadResults.innerHTML = '';
if (!items || items.length === 0) return;
items.forEach(function (item) {
var id = item.id || item.code;
var isSelected = !!selectedCountries[id];
abroadResults.appendChild(buildCountryCard(item, isSelected));
});
}
function renderAbroadSelected() {
if (!abroadSelected) return;
abroadSelected.innerHTML = '';
var keys = Object.keys(selectedCountries);
if (keys.length === 0) return;
keys.forEach(function (id) {
var item = selectedCountries[id];
abroadSelected.appendChild(buildCountryCard(item, true));
});
}
function buildCountryCard(item, isSelected) {
var id = item.id || item.code;
var price = parseFloat(item.price || item.minPrice || 0);
var priceHtml = '<span class="carei-abroad__price-val">' + (price > 0 ? price.toFixed(0) + ' zł' : 'Gratis') + '</span>';
var card = document.createElement('div');
card.className = 'carei-abroad__card' + (isSelected ? ' carei-abroad__card--selected' : '');
card.innerHTML =
'<span class="carei-abroad__flag">' + escHtml(item._countryFlag) + '</span>' +
'<span class="carei-abroad__name">' + escHtml(item._countryName) + '</span>' +
'<span class="carei-abroad__price">' + priceHtml + '</span>' +
'<span role="button" tabindex="0" class="carei-abroad__action" data-abroad-id="' + escAttr(id) + '" title="' + (isSelected ? 'Usuń' : 'Dodaj') + '">' +
(isSelected
? '<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M3 3l8 8M11 3l-8 8" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>'
: '<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M7 2v10M2 7h10" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>'
) + '</span>';
card.querySelector('.carei-abroad__action').addEventListener('click', function (e) {
e.preventDefault();
if (selectedCountries[id]) {
delete selectedCountries[id];
} else {
selectedCountries[id] = item;
}
var query = abroadInput ? abroadInput.value.trim().toLowerCase() : '';
if (query) {
var filtered = abroadItems.filter(function (it) {
return it._countryName.toLowerCase().indexOf(query) !== -1;
});
renderAbroadResults(filtered);
} else {
renderAbroadResults([]);
}
renderAbroadSelected();
});
return card;
}
// ─── Select Helpers ───────────────────────────────────────────
function populateSelect(select, options, placeholder) {
@@ -588,13 +762,31 @@
function getSelectedExtrasForApi() {
var items = [];
if (!form) return items;
var days = getRentalDays();
form.querySelectorAll('input[name="extras[]"]:checked').forEach(function (cb) {
var price = parseFloat(cb.getAttribute('data-price') || 0);
var unit = cb.getAttribute('data-unit') || 'szt.';
var amount = unit === 'doba' ? days : 1;
items.push({
id: cb.value,
name: cb.getAttribute('data-name') || '',
unit: cb.getAttribute('data-unit') || 'szt.',
amount: 1,
unit: unit,
amount: amount,
priceBeforeDiscount: price,
discount: 0,
priceAfterDiscount: price
});
});
Object.keys(selectedCountries).forEach(function (id) {
var item = selectedCountries[id];
var price = parseFloat(item.price || item.minPrice || 0);
var unit = item.unit || 'szt.';
var amount = unit === 'doba' ? days : 1;
items.push({
id: item.id || item.code,
name: item.name,
unit: unit,
amount: amount,
priceBeforeDiscount: price,
discount: 0,
priceAfterDiscount: price
@@ -898,6 +1090,7 @@
initSameReturn();
initDynamicLoading();
initClearErrors();
initAbroad();
initSubmit();
}

View File

@@ -58,11 +58,11 @@ class Carei_Reservation_Widget extends \Elementor\Widget_Base {
<div class="carei-modal-overlay" data-carei-modal role="dialog" aria-modal="true" aria-labelledby="carei-modal-title">
<div class="carei-modal">
<button type="button" class="carei-modal-close" data-carei-close-modal aria-label="Zamknij formularz">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M18 6L6 18M6 6l12 12" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
<span role="button" tabindex="0" class="carei-modal-close" data-carei-close-modal aria-label="Zamknij formularz">
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M15 5L5 15M5 5l10 10" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/>
</svg>
</button>
</span>
<h2 class="carei-modal-title" id="carei-modal-title">Wypełnij formularz rezerwacji<span>.</span></h2>
<form class="carei-form" id="carei-reservation-form" novalidate>
@@ -78,16 +78,19 @@ class Carei_Reservation_Widget extends \Elementor\Widget_Base {
<svg class="carei-form__select-arrow" width="16" height="16" viewBox="0 0 16 16"><path d="M4 6l4 4 4-4" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round"/></svg>
</div>
</div>
<div class="carei-form__field">
<label class="carei-form__label-small" for="carei-date-from">Od kiedy?</label>
<input type="datetime-local" id="carei-date-from" name="dateFrom" class="carei-form__input" required>
<div class="carei-form__field carei-form__field--date">
<div class="carei-form__date-wrap">
<svg class="carei-form__date-icon" width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2.5" y="3" width="11" height="10" rx="0.5" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/><path d="M11 1.5v2M5 1.5v2M2.5 5.5h11" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/></svg>
<label class="carei-form__date-label" for="carei-date-from">Od kiedy?</label>
<input type="datetime-local" id="carei-date-from" name="dateFrom" class="carei-form__input carei-form__input--date" required>
</div>
</div>
<div class="carei-form__field">
<label class="carei-form__label-small" for="carei-date-to">
<svg class="carei-form__icon-calendar" width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2" y="3" width="12" height="11" rx="1" stroke="currentColor" stroke-width="1.5"/><path d="M2 6h12M5 1v3M11 1v3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
Do kiedy?
</label>
<input type="datetime-local" id="carei-date-to" name="dateTo" class="carei-form__input" required>
<div class="carei-form__field carei-form__field--date">
<div class="carei-form__date-wrap">
<svg class="carei-form__date-icon" width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="2.5" y="3" width="11" height="10" rx="0.5" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/><path d="M11 1.5v2M5 1.5v2M2.5 5.5h11" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/></svg>
<label class="carei-form__date-label" for="carei-date-to">Do kiedy?</label>
<input type="datetime-local" id="carei-date-to" name="dateTo" class="carei-form__input carei-form__input--date" required>
</div>
</div>
</div>
@@ -126,6 +129,26 @@ class Carei_Reservation_Widget extends \Elementor\Widget_Base {
<!-- Ubezpieczenie + Opcje dodatkowe (ukryte do wybrania segmentu i miejsca odbioru) -->
<div id="carei-extras-wrapper" class="carei-form__extras-wrapper" style="display:none;">
<div class="carei-form__divider"><span>Wyjazd zagraniczny</span></div>
<div class="carei-form__section" id="carei-abroad-section" style="display:none;">
<label class="carei-form__checkbox-label carei-form__checkbox-label--abroad">
<input type="checkbox" id="carei-abroad-toggle" name="abroadToggle">
<span class="carei-form__checkbox-box"><svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M2 7l3.5 3.5L12 4" stroke="#fff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></span>
<span>Planuję trasę poza granicę Polski</span>
</label>
<div id="carei-abroad-search" class="carei-abroad" style="display:none;">
<div class="carei-abroad__input-wrap">
<svg class="carei-abroad__plus-icon" width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M8 2v12M2 8h12" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>
<input type="text" id="carei-abroad-input" class="carei-abroad__input" placeholder="Wyszukaj i dodaj kraj na trasie">
<span role="button" tabindex="0" class="carei-abroad__clear" id="carei-abroad-clear" title="Wyczyść">
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M3 3l8 8M11 3l-8 8" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
</span>
</div>
<div class="carei-abroad__results" id="carei-abroad-results"></div>
<div class="carei-abroad__selected" id="carei-abroad-selected"></div>
</div>
</div>
<div class="carei-form__divider"><span>Ubezpieczenie</span></div>
<div class="carei-form__section">
<div class="carei-form__row" id="carei-insurance-container">
@@ -148,51 +171,67 @@ class Carei_Reservation_Widget extends \Elementor\Widget_Base {
<div class="carei-form__section">
<div class="carei-form__row">
<div class="carei-form__field">
<label class="carei-form__label-small" for="carei-firstname">Imię</label>
<input type="text" id="carei-firstname" name="firstName" class="carei-form__input" required>
<div class="carei-form__float-wrap">
<input type="text" id="carei-firstname" name="firstName" class="carei-form__input carei-form__input--float" placeholder=" " required>
<label class="carei-form__float-label" for="carei-firstname">Imię</label>
</div>
</div>
<div class="carei-form__field">
<label class="carei-form__label-small" for="carei-lastname">Nazwisko</label>
<input type="text" id="carei-lastname" name="lastName" class="carei-form__input" required>
<div class="carei-form__float-wrap">
<input type="text" id="carei-lastname" name="lastName" class="carei-form__input carei-form__input--float" placeholder=" " required>
<label class="carei-form__float-label" for="carei-lastname">Nazwisko</label>
</div>
</div>
</div>
<div class="carei-form__row carei-form__row--address">
<div class="carei-form__field">
<label class="carei-form__label-small" for="carei-city">Miejscowość</label>
<input type="text" id="carei-city" name="city" class="carei-form__input" required>
<div class="carei-form__float-wrap">
<input type="text" id="carei-city" name="city" class="carei-form__input carei-form__input--float" placeholder=" " required>
<label class="carei-form__float-label" for="carei-city">Miejscowość</label>
</div>
</div>
<div class="carei-form__field carei-form__field--zipcode">
<label class="carei-form__label-small" for="carei-zipcode">Kod pocztowy</label>
<input type="text" id="carei-zipcode" name="zipCode" class="carei-form__input" placeholder="00-000" maxlength="6" required>
<div class="carei-form__float-wrap">
<input type="text" id="carei-zipcode" name="zipCode" class="carei-form__input carei-form__input--float" placeholder=" " maxlength="6" required>
<label class="carei-form__float-label" for="carei-zipcode">Kod pocztowy</label>
</div>
</div>
<div class="carei-form__field">
<label class="carei-form__label-small" for="carei-street">Ulica i nr domu</label>
<input type="text" id="carei-street" name="street" class="carei-form__input" required>
</div>
</div>
<div class="carei-form__row">
<div class="carei-form__field">
<label class="carei-form__label-small" for="carei-email">Adres e-mail</label>
<input type="email" id="carei-email" name="email" class="carei-form__input" required>
</div>
<div class="carei-form__field">
<label class="carei-form__label-small" for="carei-phone">Nr telefonu</label>
<div class="carei-form__phone-wrap">
<div class="carei-form__phone-prefix">
<span class="carei-form__phone-flag">🇵🇱</span>
<span class="carei-form__phone-code">+48</span>
</div>
<input type="tel" id="carei-phone" name="phone" class="carei-form__input carei-form__input--phone" placeholder="___ ___ ___" required>
<div class="carei-form__float-wrap">
<input type="text" id="carei-street" name="street" class="carei-form__input carei-form__input--float" placeholder=" " required>
<label class="carei-form__float-label" for="carei-street">Ulica i nr domu</label>
</div>
</div>
</div>
<div class="carei-form__row">
<div class="carei-form__field">
<label class="carei-form__label-small" for="carei-pesel">PESEL</label>
<input type="text" id="carei-pesel" name="pesel" class="carei-form__input" maxlength="11" placeholder="00000000000" required>
<div class="carei-form__float-wrap">
<input type="email" id="carei-email" name="email" class="carei-form__input carei-form__input--float" placeholder=" " required>
<label class="carei-form__float-label" for="carei-email">Adres e-mail</label>
</div>
</div>
<div class="carei-form__field">
<div class="carei-form__phone-wrap">
<label class="carei-form__phone-label" for="carei-phone">Nr telefonu</label>
<div class="carei-form__phone-row">
<div class="carei-form__phone-prefix">
<span class="carei-form__phone-flag">🇵🇱</span>
<span class="carei-form__phone-code">+48</span>
</div>
<input type="tel" id="carei-phone" name="phone" class="carei-form__input carei-form__input--phone" placeholder="___ ___ ___" required>
</div>
</div>
</div>
</div>
<div class="carei-form__row">
<div class="carei-form__field">
<div class="carei-form__float-wrap">
<input type="text" id="carei-pesel" name="pesel" class="carei-form__input carei-form__input--float" placeholder=" " maxlength="11" required>
<label class="carei-form__float-label" for="carei-pesel">PESEL</label>
</div>
</div>
<div class="carei-form__field"></div>
</div>

BIN
wp-content/themes/.DS_Store vendored Normal file

Binary file not shown.

BIN
wp-includes/.DS_Store vendored Normal file

Binary file not shown.

BIN
wp-includes/Requests/.DS_Store vendored Normal file

Binary file not shown.

BIN
wp-includes/SimplePie/.DS_Store vendored Normal file

Binary file not shown.

BIN
wp-includes/blocks/.DS_Store vendored Normal file

Binary file not shown.

BIN
wp-includes/images/.DS_Store vendored Normal file

Binary file not shown.

BIN
wp-includes/js/.DS_Store vendored Normal file

Binary file not shown.

BIN
wp-includes/rest-api/.DS_Store vendored Normal file

Binary file not shown.

BIN
wp-includes/sodium_compat/.DS_Store vendored Normal file

Binary file not shown.