This commit is contained in:
2026-04-01 20:15:45 +02:00
parent 92b7a2a95e
commit 9b36f8fec3
35 changed files with 2371 additions and 31 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@@ -47,6 +47,15 @@ Plugin Elementor do rezerwacji samochodu na stronie carei.pagedev.pl, zintegrowa
| Inline display:none for steps | 4 | CSS class conflict resolution | | Inline display:none for steps | 4 | CSS class conflict resolution |
| Calendar picker opacity:0 stretch | 7 | Ukrycie natywnej ikonki z zachowaniem kliknięcia | | Calendar picker opacity:0 stretch | 7 | Ukrycie natywnej ikonki z zachowaniem kliknięcia |
| Search form niezależne API loading | 7 | Dane dostępne od razu, niezależnie od modala | | Search form niezależne API loading | 7 | Dane dostępne od razu, niezależnie od modala |
| Static city→SVG coords (no geocoding) | 8 | Prostota, brak zewnętrznych zależności |
| Branch name D/L suffix stripping | 8 | API zwraca warianty Dworzec/Lotnisko — deduplikacja |
| CSS ::after for city separators | 8 | Zapobiega orphanowaniu `\|` na początku linii |
## Validated Requirements (Milestone v0.3)
- ✓ Mapa SVG Polski z dynamicznymi pinami oddziałów i tooltipami — Phase 8
- ✓ Siatka miast oddziałowych (widget Elementor) — Phase 8
- ✓ Grid oddziałów z adresami (widget Elementor) — Phase 8
- ✓ Cachowanie `/branch/list` z TTL 60 min — Phase 8
## Out of Scope (backlog) ## Out of Scope (backlog)
- Ubezpieczenie (pakiet Soft/Premium) — czeka na API Softra - Ubezpieczenie (pakiet Soft/Premium) — czeka na API Softra

View File

@@ -35,5 +35,16 @@ Kompaktowy widget Elementor "Carei Search Form" osadzany w sekcji hero. Pola: se
--- ---
## Milestone v0.3: Mapa Oddziałów + Cache API
**Goal:** Wizualna prezentacja sieci oddziałów Carei — interaktywna mapa SVG z pinami i siatka miast, plus ujednolicone cachowanie API.
**Status:** Complete ✅
### Phase 8: Mapa oddziałów + siatka miast + cache API ✅ Complete
Dwa widgety Elementor: (1) mapa Polski SVG z dynamicznymi pinami oddziałów i tooltipami adresowymi, (2) siatka miast. Cachowanie `/branch/list` z TTL 60 min.
---
### Backlog (do realizacji gdy API będzie gotowe) ### Backlog (do realizacji gdy API będzie gotowe)
- **Ubezpieczenie:** Sekcja "Pakiet ochrony Soft/Premium" jak na Figmie. Wymaga dedykowanych pozycji ubezpieczeniowych w API pricelist. - **Ubezpieczenie:** Sekcja "Pakiet ochrony Soft/Premium" jak na Figmie. Wymaga dedykowanych pozycji ubezpieczeniowych w API pricelist.

View File

@@ -2,14 +2,15 @@
## Current Position ## Current Position
Milestone: v0.2 Wyjazd Zagraniczny — Complete Milestone: v0.3 Mapa Oddziałów + Cache API — Complete
Phase: 7 of 7 — All phases complete Phase: 8 of 8 — All phases complete
Status: Milestone v0.2 complete Status: Milestone v0.3 complete
Last activity: 2026-04-01 — Phase 6 retroactively closed, Phase 7 complete Last activity: 2026-04-01 — Phase 8 complete, loop closed
Progress: Progress:
- Milestone v0.1: [██████████] 100% ✅ - Milestone v0.1: [██████████] 100% ✅
- Milestone v0.2: [██████████] 100% ✅ - Milestone v0.2: [██████████] 100% ✅
- Milestone v0.3: [██████████] 100% ✅
## Loop Position ## Loop Position
@@ -22,6 +23,6 @@ PLAN ──▶ APPLY ──▶ UNIFY
## Session Continuity ## Session Continuity
Last session: 2026-04-01 Last session: 2026-04-01
Stopped at: Milestone v0.2 complete Stopped at: Milestone v0.3 complete
Next action: Plan new milestone or new work Next action: Plan new milestone or new work
Resume file: .paul/ROADMAP.md Resume file: .paul/ROADMAP.md

View File

@@ -0,0 +1,219 @@
---
phase: 08-map-and-cities-widgets
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
- wp-content/plugins/carei-reservation/includes/class-map-widget.php
- wp-content/plugins/carei-reservation/includes/class-cities-widget.php
- wp-content/plugins/carei-reservation/includes/class-softra-api.php
- wp-content/plugins/carei-reservation/carei-reservation.php
- wp-content/plugins/carei-reservation/assets/css/carei-reservation.css
- wp-content/plugins/carei-reservation/assets/js/carei-reservation.js
autonomous: false
---
<objective>
## Goal
Dwa nowe widgety Elementor: (1) interaktywna mapa Polski z dynamicznymi pinami oddziałów i tooltipami adresowymi, (2) siatka miast oddziałowych. Plus ujednolicone cachowanie odpowiedzi API Softra (60 min).
## Purpose
Wizualna prezentacja sieci oddziałów Carei na stronie — mapa z pinami i lista miast budują zaufanie klienta i ułatwiają wybór lokalizacji.
## Output
- `class-map-widget.php` — widget Elementor z mapą SVG Polski + dynamiczne piny
- `class-cities-widget.php` — widget Elementor z siatką miast
- Rozszerzony cache w `class-softra-api.php` — transient 60 min na `/branch/list`
- Zarejestrowane widgety w `carei-reservation.php`
- Style i JS w istniejących plikach assets
</objective>
<context>
## Project Context
@.paul/PROJECT.md
@.paul/ROADMAP.md
@.paul/STATE.md
## Source Files
@wp-content/plugins/carei-reservation/carei-reservation.php
@wp-content/plugins/carei-reservation/includes/class-softra-api.php
@wp-content/plugins/carei-reservation/includes/class-search-widget.php (wzorzec widgetu)
@wp-content/plugins/carei-reservation/assets/css/carei-reservation.css
@wp-content/plugins/carei-reservation/assets/js/carei-reservation.js
</context>
<skills>
No specialized flows configured.
</skills>
<acceptance_criteria>
## AC-1: Mapa Polski z dynamicznymi pinami oddziałów
```gherkin
Given strona z widgetem Carei Map załadowana
When dane oddziałów pobrane z API (lub cache)
Then na mapie SVG Polski wyświetlają się czerwone piny w lokalizacjach odpowiadających miastom oddziałów
And po najechaniu na pin pojawia się tooltip z adresem oddziału (ulica, kod, miasto)
And po kliknięciu pina tooltip pozostaje widoczny (toggle)
```
## AC-2: Siatka miast oddziałowych
```gherkin
Given strona z widgetem Carei Cities załadowana
When dane oddziałów pobrane z API (lub cache)
Then wyświetla się siatka z nazwami miast oddziałów rozdzielonymi separatorem "|"
And miasta są unikalne (bez duplikatów nawet jeśli oddział ma wiele branchy w jednym mieście)
And układ jest responsywny (grid na desktop, kolumna na mobile)
```
## AC-3: Cachowanie odpowiedzi API z TTL 60 min
```gherkin
Given plugin Carei Reservation aktywny
When frontend lub widget pobiera dane oddziałów z /branch/list
Then wynik jest cachowany jako WP transient z TTL 60 minut
And kolejne żądania w ciągu 60 min nie generują zapytań do Softra API
And po upływie TTL dane są odświeżane z API
```
</acceptance_criteria>
<tasks>
<task type="auto">
<name>Task 1: Cache API + Widget mapki Polski z pinami</name>
<files>
wp-content/plugins/carei-reservation/includes/class-softra-api.php,
wp-content/plugins/carei-reservation/includes/class-map-widget.php,
wp-content/plugins/carei-reservation/carei-reservation.php,
wp-content/plugins/carei-reservation/assets/css/carei-reservation.css,
wp-content/plugins/carei-reservation/assets/js/carei-reservation.js
</files>
<action>
**1a. Cachowanie `/branch/list` (class-softra-api.php):**
- Dodaj metodę `get_branches_cached()` opakowującą `get_branches()` w transient `carei_branches_list` z TTL 60 min (HOUR_IN_SECONDS).
- Zmień `get_segments_branches_map()` by korzystała z `get_branches_cached()` zamiast `get_branches()`.
- Dodaj endpoint REST `/branches-full` w REST proxy zwracający pełne dane branchy (z description/address) — istniejący `/branches` zwraca tylko nazwy.
**1b. Widget mapy (class-map-widget.php):**
- Nowa klasa `Carei_Map_Widget extends \Elementor\Widget_Base`
- `get_name()``'carei-map'`, `get_title()``'Carei Map'`
- W `render()`:
- Pobierz oddziały z REST API `/carei/v1/branches-full` przez JS (lub inline z PHP jeśli cache aktywny)
- Wyrenderuj kontener `<div class="carei-map">` z inline SVG mapy Polski (kontur województw)
- SVG mapy: użytkownik dostarczy kod SVG — na razie placeholder z prostym konturem Polski
- Mapowanie miast na współrzędne SVG:
- W PHP: tablica asocjacyjna `CITY_COORDINATES` mapująca nazwy miast (lowercase, bez polskich znaków) na współrzędne [x, y] w viewBox SVG
- Miasta znane w Carei: Warszawa, Białystok, Wrocław, Kraków, Gdańsk, Poznań, Katowice, Łódź, Lublin, Szczecin, Rzeszów, Bydgoszcz, Olsztyn, Kielce, Opole, Zielona Góra, Radom itp.
- Przekaż współrzędne do JS przez `wp_localize_script` lub data-attribute
- W JS: dynamicznie dodaj `<circle>` (piny) na mapie SVG w pozycjach z mapowania
- Tooltip: na hover/click nad pinem — `<div class="carei-map__tooltip">` z adresem z pola `description` brancha
- Styl pina: czerwone kółko (#FF0000), r=6, hover r=8 z transition
- Styl tooltipa: ciemne tło (#2F2482), biały tekst, strzałka (jak na Figmie)
**1c. Rejestracja widgetu:**
- W `carei-reservation.php` w hooku `elementor/widgets/register`: require + register `Carei_Map_Widget`
**Avoid:**
- NIE używaj zewnętrznych bibliotek mapowych (Leaflet, Google Maps) — to prosta mapa SVG
- NIE hardkoduj danych oddziałów — zawsze z API/cache
</action>
<verify>
- Widget "Carei Map" widoczny w panelu Elementor
- Mapa SVG renderuje się z pinami w lokalizacjach oddziałów
- Hover na pinie pokazuje tooltip z adresem
- Drugie załadowanie strony nie generuje nowego requestu do Softra (cache aktywny)
</verify>
<done>AC-1 satisfied: Mapa z dynamicznymi pinami i tooltipami. AC-3 satisfied: Cache 60 min na branch/list.</done>
</task>
<task type="auto">
<name>Task 2: Widget siatki miast</name>
<files>
wp-content/plugins/carei-reservation/includes/class-cities-widget.php,
wp-content/plugins/carei-reservation/carei-reservation.php,
wp-content/plugins/carei-reservation/assets/css/carei-reservation.css,
wp-content/plugins/carei-reservation/assets/js/carei-reservation.js
</files>
<action>
**2a. Widget miast (class-cities-widget.php):**
- Nowa klasa `Carei_Cities_Widget extends \Elementor\Widget_Base`
- `get_name()``'carei-cities'`, `get_title()``'Carei Cities'`
- W `render()`:
- Pobierz oddziały z cache/API (ten sam endpoint co mapa)
- Wyciągnij unikalne nazwy miast z pola description branchy (parse miasto z adresu)
- Renderuj `<div class="carei-cities">` z siatką miast
- HTML: `<span class="carei-cities__item">Miasto</span>` rozdzielone separatorem `|`
- Layout: CSS grid/flex, 5 kolumn na desktop (jak na Figmie), 2-3 kolumny na tablet, 1 na mobile
- Font: Albert Sans, kolor #2F2482
- Miasta dynamiczne — jeśli oddział dodany w Softra, automatycznie pojawia się w widgecie
**2b. Rejestracja widgetu:**
- W `carei-reservation.php`: require + register `Carei_Cities_Widget`
**Avoid:**
- NIE hardkoduj listy miast
- NIE duplikuj requestów — użyj tego samego cache co mapa
</action>
<verify>
- Widget "Carei Cities" widoczny w panelu Elementor
- Siatka miast renderuje się z unikalnymi miastami z API
- Responsywność: 5 kolumn desktop → mniej na mobile
- Brak duplikatów miast
</verify>
<done>AC-2 satisfied: Siatka miast dynamiczna, responsywna, unikalne wartości.</done>
</task>
<task type="checkpoint:human-verify" gate="blocking">
<what-built>Dwa widgety Elementor: mapa Polski z pinami oddziałów + siatka miast. Cachowanie API 60 min.</what-built>
<how-to-verify>
1. Otwórz stronę w Elementorze, dodaj widget "Carei Map" — sprawdź czy piny są na mapie
2. Najedź na pin — tooltip z adresem powinien się pojawić
3. Dodaj widget "Carei Cities" — sprawdź siatkę miast
4. Sprawdź responsywność (mobile preview w Elementorze)
5. Opcjonalnie: podaj kod SVG mapy Polski do zastąpienia placeholdera
</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-elementor-widget.php (główny widget rezerwacji)
- wp-content/plugins/carei-reservation/includes/class-admin-panel.php (admin panel)
- Istniejące endpointy REST (nie zmieniaj zachowania `/branches`, `/car-classes` itd.)
- Logika formularza rezerwacji w JS (sekcje modal, booking flow)
## SCOPE LIMITS
- Mapa to SVG statyczny z dynamicznymi pinami — NIE interaktywna mapa z zoomem
- Brak geokodowania w runtime — współrzędne miast zmapowane statycznie w PHP
- Tooltip prosty (adres) — bez linków, bez routingu do formularza
- Cachowanie tylko na `/branch/list` — inne endpointy bez zmian w tym planie
</boundaries>
<verification>
Before declaring plan complete:
- [ ] Widget "Carei Map" renderuje mapę z pinami na prawidłowych pozycjach
- [ ] Tooltip na hover/click pokazuje adres oddziału
- [ ] Widget "Carei Cities" wyświetla unikalne miasta w siatce
- [ ] Cache transient `carei_branches_list` aktywny z TTL 60 min
- [ ] Responsywność obu widgetów (desktop + mobile)
- [ ] Brak błędów JS w konsoli
- [ ] Brak broken layouts w istniejących widgetach (rezerwacja, search form)
</verification>
<success_criteria>
- Oba widgety dostępne w Elementorze i renderują dane z API
- Piny na mapie odpowiadają miastom oddziałów z Softra
- Tooltips wyświetlają adresy
- Siatka miast dynamiczna i responsywna
- Cache 60 min działa — brak nadmiarowych requestów do API
- Istniejąca funkcjonalność nienaruszona
</success_criteria>
<output>
After completion, create `.paul/phases/08-map-and-cities-widgets/08-01-SUMMARY.md`
</output>

View File

@@ -0,0 +1,145 @@
---
phase: 08-map-and-cities-widgets
plan: 01
subsystem: ui
tags: [elementor, svg, map, api-cache, transient]
requires:
- phase: 01-reservation-form-plugin
provides: Softra API client, REST proxy, plugin bootstrap
provides:
- Carei Map widget (SVG map with dynamic pins + tooltips)
- Carei Cities widget (city name grid)
- Carei Branches widget (branch grid with addresses)
- Branches API caching (60min transient)
- REST endpoint /branches-full
affects: []
tech-stack:
added: []
patterns:
- "Branch name cleaning: strip D/L suffixes, NAME_FIXES for truncated names"
- "City coordinates: static PHP array mapping normalized names to SVG viewBox coords"
key-files:
created:
- wp-content/plugins/carei-reservation/includes/class-map-widget.php
- wp-content/plugins/carei-reservation/includes/class-cities-widget.php
- wp-content/plugins/carei-reservation/includes/class-branches-widget.php
modified:
- wp-content/plugins/carei-reservation/includes/class-softra-api.php
- wp-content/plugins/carei-reservation/includes/class-rest-proxy.php
- wp-content/plugins/carei-reservation/carei-reservation.php
- wp-content/plugins/carei-reservation/assets/css/carei-reservation.css
- wp-content/plugins/carei-reservation/assets/js/carei-reservation.js
key-decisions:
- "Branch name D=Dworzec, L=Lotnisko — strip suffixes, deduplicate to base city"
- "Tooltip format: Oddział [City] + ul. Street + ZipCode City"
- "Branches widget added beyond original plan scope"
- "Cities separator via CSS ::after to prevent line-start orphan |"
patterns-established:
- "NAME_FIXES const for API name corrections (shared across widgets)"
- "get_branches_cached() as single source for all branch data"
duration: ~45min
started: 2026-04-01T17:30:00Z
completed: 2026-04-01T18:15:00Z
---
# Phase 8 Plan 01: Map, Cities & Branches Widgets Summary
**Three Elementor widgets for branch visualization: SVG map with dynamic pins/tooltips, city name list, and full branch grid with addresses. Plus 60-min API cache.**
## Performance
| Metric | Value |
|--------|-------|
| Duration | ~45min |
| Tasks | 3 completed (2 auto + 1 checkpoint) |
| Files modified | 7 (3 created, 4 modified) |
## Acceptance Criteria Results
| Criterion | Status | Notes |
|-----------|--------|-------|
| AC-1: Mapa Polski z dynamicznymi pinami | Pass | Real SVG (Vector.svg), pins from API, tooltip with address |
| AC-2: Siatka miast oddziałowych | Pass | Unique cities, ::after separators, responsive |
| AC-3: Cachowanie API 60 min | Pass | `get_branches_cached()` with HOUR_IN_SECONDS transient |
## Accomplishments
- SVG map of Poland (user-provided Vector.svg) with dynamic red pins positioned by city coordinate mapping, tooltips showing "Oddział [City] / ul. Street / ZipCode City"
- Cities widget with deduplicated, title-cased names from API, CSS ::after separators that never orphan to line start
- Branches grid widget (5→3→2→1 columns responsive) with full address data from API fields (street, zipCode, city)
- Unified branch name cleaning: D/L suffix stripping, NAME_FIXES for truncated API names (BYDGOSZC→BYDGOSZCZ, GORZÓW WIE→GORZÓW WIELKOPOLSKI, RZSZÓW→RZESZÓW, SK-KAM→skip)
- 60-min transient cache on /branch/list, used by all three widgets via single `get_branches_cached()` method
## Files Created/Modified
| File | Change | Purpose |
|------|--------|---------|
| `includes/class-map-widget.php` | Created | SVG map widget with pins, tooltips, city coords |
| `includes/class-cities-widget.php` | Created | City name grid widget |
| `includes/class-branches-widget.php` | Created | Branch grid with addresses |
| `includes/class-softra-api.php` | Modified | Added `get_branches_cached()` with 60min transient |
| `includes/class-rest-proxy.php` | Modified | Added `/branches-full` endpoint |
| `carei-reservation.php` | Modified | Registered 3 new widgets |
| `assets/css/carei-reservation.css` | Modified | Styles for map, cities, branches widgets |
| `assets/js/carei-reservation.js` | Modified | Dynamic pin rendering + tooltip logic |
## Decisions Made
| Decision | Rationale | Impact |
|----------|-----------|--------|
| Static city→SVG coordinate mapping in PHP | No runtime geocoding, simple and fast | New cities need manual coord addition |
| D suffix = Dworzec, display as "Oddział [City]" | User request for consistent naming | All tooltips show "Oddział X" format |
| CSS ::after for city separators | Prevents `\|` orphaning to line start on wrap | Cleaner than separate `<span>` elements |
| Added Branches widget (not in original plan) | User requested during execution | Extra widget, no negative impact |
## Deviations from Plan
### Summary
| Type | Count | Impact |
|------|-------|--------|
| Scope additions | 1 | Branches grid widget added |
| Auto-fixed | 3 | API name cleaning, separator orphans, tooltip content |
**Total impact:** Scope addition was user-requested. Auto-fixes were essential for data quality.
### Auto-fixed Issues
**1. API branch names with D/L suffixes causing 39 duplicates**
- Found during: checkpoint verification
- Issue: API returns "GDAŃSK", "GDAŃSK D", "GDAŃSK L" as separate branches
- Fix: Strip suffixes, NAME_FIXES for truncated names, deduplicate
- Verification: 17 unique cities displayed
**2. Separator `|` orphaning to new line start**
- Found during: user review
- Fix: Replaced `<span>` separator with CSS `::after` pseudo-element
**3. Tooltip showing raw API description instead of formatted address**
- Found during: user review
- Fix: Built address from `street`, `zipCode`, `city` API fields
## Next Phase Readiness
**Ready:**
- All branch visualization widgets operational
- API cache in place for all branch data consumers
- Branch name cleaning pattern reusable
**Concerns:**
- City coordinates are static — new Softra branches in unmapped cities won't show pins
- Some API zipCodes are null (e.g., Białystok)
**Blockers:** None
---
*Phase: 08-map-and-cities-widgets, Plan: 01*
*Completed: 2026-04-01*

View File

@@ -0,0 +1,2 @@
[ 2171ms] [LOG] JQMIGRATE: Migrate is installed, version 3.4.1 @ https://carei.pagedev.pl/wp-includes/js/jquery/jquery-migrate.min.js?ver=3.4.1:1
[ 2728ms] [ERROR] Failed to load resource: the server responded with a status of 404 () @ https://carei.pagedev.pl/favicon.ico:0

View File

@@ -0,0 +1 @@
[ 230ms] [LOG] JQMIGRATE: Migrate is installed, version 3.4.1 @ https://carei.pagedev.pl/wp-includes/js/jquery/jquery-migrate.min.js?ver=3.4.1:1

View File

@@ -0,0 +1,618 @@
- generic [active] [ref=e1]:
- link "Przejdź do treści" [ref=e2] [cursor=pointer]:
- /url: "#content"
- banner [ref=e3]:
- generic [ref=e5]:
- link [ref=e7] [cursor=pointer]:
- /url: https://carei.pagedev.pl
- navigation "Menu" [ref=e9]:
- list [ref=e10]:
- listitem [ref=e11]:
- link "Wynajem długoterminowy" [ref=e12] [cursor=pointer]:
- /url: https://carei.pagedev.pl/wynajem-dlugoterminowy/
- listitem [ref=e13]:
- link "Wynajem krótkoterminowy" [ref=e14] [cursor=pointer]:
- /url: "#"
- listitem [ref=e15]:
- link "Kontakt" [ref=e16] [cursor=pointer]:
- /url: https://carei.pagedev.pl/kontakt/
- generic [ref=e18]:
- list [ref=e20]:
- listitem [ref=e21]:
- link "+48 572 663 614" [ref=e22] [cursor=pointer]:
- /url: tel:+48572663614
- img [ref=e24]
- generic [ref=e30]: +48 572 663 614
- generic [ref=e32]:
- button "Złóż zapytanie o rezerwację" [ref=e33] [cursor=pointer]:
- img [ref=e34]
- text: Złóż zapytanie o rezerwację
- option "Wybierz segment pojazdu" [disabled] [selected]
- option "Miejsce odbioru" [disabled] [selected]
- generic [ref=e39]:
- generic [ref=e41]:
- generic [ref=e42]:
- heading "Wypożyczalnia samochodów osobowych" [level=4] [ref=e44]
- heading "Wybierz segment i zacznij podróż." [level=2] [ref=e46]
- paragraph [ref=e48]:
- text: Otrzymaj auto w ciągu
- strong [ref=e49]: 1h
- text: od przyjęcia przez nas zlecenia.
- generic [ref=e53]:
- heading "Wypełnij formularz rezerwacji." [level=2] [ref=e54]
- generic [ref=e55]:
- generic [ref=e57]:
- combobox [ref=e58] [cursor=pointer]:
- option "Wybierz segment" [disabled] [selected]
- img
- generic [ref=e59]:
- generic [ref=e61]:
- img
- generic: Od kiedy?
- textbox "Od kiedy?" [ref=e62]
- generic [ref=e64]:
- img
- generic: Do kiedy?
- textbox "Do kiedy?" [ref=e65]
- generic [ref=e67]:
- img
- combobox [ref=e68] [cursor=pointer]:
- option "Miejsce odbioru" [disabled] [selected]
- img
- generic [ref=e70] [cursor=pointer]:
- checkbox "Zwrot w tej samej lokalizacji" [checked]
- img [ref=e72]
- generic [ref=e74]: Zwrot w tej samej lokalizacji
- button "Złóż zapytanie o rezerwację" [ref=e75] [cursor=pointer]:
- img [ref=e76]
- text: Złóż zapytanie o rezerwację
- generic [ref=e79]:
- generic [ref=e81]:
- img [ref=e84]
- generic [ref=e91]:
- heading "Szybka i dokładna obsługa zamówień" [level=3] [ref=e92]
- paragraph [ref=e93]: Gwarantujemy pełną gotowość auta na Twój przyjazd.
- generic [ref=e99]:
- img [ref=e102]
- generic [ref=e108]:
- heading "Bez opłat przygotowawczych" [level=3] [ref=e109]
- paragraph [ref=e110]: Stawiamy na jasne zasady, nie doliczamy ukrytych kosztów.
- generic [ref=e116]:
- img [ref=e119]
- generic [ref=e123]:
- heading "Atrakcyjne promocje weekendowe" [level=3] [ref=e124]
- paragraph [ref=e125]: Oszczędzaj na wynajmie planując weekendowy wyjazd.
- generic [ref=e127]:
- heading "Jak wypożyczyć auto krótkoterminowo?" [level=2] [ref=e132]
- paragraph [ref=e137]: Najszybciej i najprościej zrobić to z Carei w ciągu 1h od przyjęcia przez nas zlecenia otrzymasz już samochód.
- generic [ref=e142]:
- generic [ref=e145]:
- generic [ref=e146]:
- generic: "1."
- generic [ref=e147]:
- heading "Złóż zapytanie o rezerwację" [level=3] [ref=e148]
- paragraph [ref=e149]: W formularzu zaznacz jaka oferta Cię interesuje i podaj nam dane do kontaktu.
- generic [ref=e152]:
- generic [ref=e153]:
- generic: "2."
- generic [ref=e154]:
- heading "Skontaktuje się z Tobą obsługa klienta" [level=3] [ref=e155]
- paragraph [ref=e156]: Nasza infolinia działa 24h na dobę i przedstawi Ci konkretną propozycję
- generic [ref=e159]:
- generic [ref=e160]:
- generic: "3."
- generic [ref=e161]:
- heading "Odbierz kluczyki" [level=3] [ref=e162]
- paragraph [ref=e163]: Gwarantujemy minimum formalności przy odbiorze auta.
- link "Złóż zapytanie o rezerwację" [ref=e170] [cursor=pointer]:
- /url: "#"
- generic [ref=e171]:
- img [ref=e173]
- generic [ref=e175]: Złóż zapytanie o rezerwację
- generic [ref=e183]:
- heading "Chcesz wynająć auto na dłużej niż miesiąc?" [level=2] [ref=e185]
- paragraph [ref=e187]: Przygotujemy dla Ciebie atrakcyjne warunki wynajmu długoterminowego.
- link "Oferta najmu długoterminowego" [ref=e189] [cursor=pointer]:
- /url: "#"
- generic [ref=e191]: Oferta najmu długoterminowego
- generic [ref=e196]:
- img [ref=e201]
- generic [ref=e219]:
- heading "17 oddziałów w całej Polsce" [level=3] [ref=e221]:
- text: 17 oddziałów
- text: w całej Polsce
- heading "Podróżuj z Carei!" [level=2] [ref=e223]
- generic [ref=e224]:
- paragraph [ref=e225]: Od 2006 roku zajmujemy się szeroko rozumianym wynajmem samochodów osobowych na terenie Polski.
- paragraph [ref=e226]:
- text: W naszej ofercie znajdują się
- strong [ref=e227]: samochody standardowe oraz klasy premium
- text: .
- generic [ref=e230]:
- generic [ref=e231]: BIAŁYSTOK
- generic [ref=e232]: "|"
- generic [ref=e233]: BYDGOSZC D
- generic [ref=e234]: "|"
- generic [ref=e235]: BYDGOSZC L
- generic [ref=e236]: "|"
- generic [ref=e237]: BYDGOSZCZ
- generic [ref=e238]: "|"
- generic [ref=e239]: GDAŃSK
- generic [ref=e240]: "|"
- generic [ref=e241]: GDAŃSK D
- generic [ref=e242]: "|"
- generic [ref=e243]: GDAŃSK L
- generic [ref=e244]: "|"
- generic [ref=e245]: GORZÓW WIE
- generic [ref=e246]: "|"
- generic [ref=e247]: KATOWICE
- generic [ref=e248]: "|"
- generic [ref=e249]: KATOWICE D
- generic [ref=e250]: "|"
- generic [ref=e251]: KATOWICE L
- generic [ref=e252]: "|"
- generic [ref=e253]: KIELCE
- generic [ref=e254]: "|"
- generic [ref=e255]: KRAKÓW
- generic [ref=e256]: "|"
- generic [ref=e257]: KRAKÓW D
- generic [ref=e258]: "|"
- generic [ref=e259]: KRAKÓW L
- generic [ref=e260]: "|"
- generic [ref=e261]: LUBLIN
- generic [ref=e262]: "|"
- generic [ref=e263]: LUBLIN D
- generic [ref=e264]: "|"
- generic [ref=e265]: LUBLIN L
- generic [ref=e266]: "|"
- generic [ref=e267]: OLSZTYN
- generic [ref=e268]: "|"
- generic [ref=e269]: POZNAŃ
- generic [ref=e270]: "|"
- generic [ref=e271]: POZNAŃ D
- generic [ref=e272]: "|"
- generic [ref=e273]: POZNAŃ L
- generic [ref=e274]: "|"
- generic [ref=e275]: RADOM
- generic [ref=e276]: "|"
- generic [ref=e277]: RADOM D
- generic [ref=e278]: "|"
- generic [ref=e279]: RADOM L
- generic [ref=e280]: "|"
- generic [ref=e281]: RUMIA D
- generic [ref=e282]: "|"
- generic [ref=e283]: RZESZÓW
- generic [ref=e284]: "|"
- generic [ref=e285]: RZESZÓW L
- generic [ref=e286]: "|"
- generic [ref=e287]: RZSZÓW D
- generic [ref=e288]: "|"
- generic [ref=e289]: SK-KAM
- generic [ref=e290]: "|"
- generic [ref=e291]: SOPOT D
- generic [ref=e292]: "|"
- generic [ref=e293]: SZCZECIN
- generic [ref=e294]: "|"
- generic [ref=e295]: WARSZAWA
- generic [ref=e296]: "|"
- generic [ref=e297]: WARSZAWA D
- generic [ref=e298]: "|"
- generic [ref=e299]: WARSZAWA L
- generic [ref=e300]: "|"
- generic [ref=e301]: WROCŁAW
- generic [ref=e302]: "|"
- generic [ref=e303]: WROCŁAW D
- generic [ref=e304]: "|"
- generic [ref=e305]: WROCŁAW L
- generic [ref=e306]: "|"
- generic [ref=e307]: ŁÓDŹ
- generic [ref=e314]:
- heading "Wypożycz auto na swój wyjazd." [level=2] [ref=e316]
- paragraph [ref=e318]:
- text: Szybka obsługa zamówienia
- text: i minimum formalności.
- generic [ref=e319]:
- region "Carousel" [ref=e320]:
- generic [ref=e321]:
- group [ref=e322]:
- generic [ref=e326]:
- heading [level=3] [ref=e328]: Segment B
- paragraph [ref=e330]: "Przykładowy model: Toyota Yaris"
- paragraph [ref=e332]: Od 79 zł brutto / doba
- link [ref=e334] [cursor=pointer]:
- /url: "#"
- generic [ref=e335]:
- img [ref=e337]
- generic [ref=e339]: Złóż zapytanie o rezerwację
- group [ref=e340]:
- generic [ref=e344]:
- heading [level=3] [ref=e346]: Segment LUX
- paragraph [ref=e348]: "Przykładowy model: Toyota Yaris"
- paragraph [ref=e350]: Od 79 zł brutto / doba
- link [ref=e352] [cursor=pointer]:
- /url: "#"
- generic [ref=e353]:
- img [ref=e355]
- generic [ref=e357]: Złóż zapytanie o rezerwację
- group [ref=e358]:
- generic [ref=e362]:
- heading [level=3] [ref=e364]: Segment C/C+
- paragraph [ref=e366]: "Przykładowy model: Toyota Yaris"
- paragraph [ref=e368]: Od 79 zł brutto / doba
- link [ref=e370] [cursor=pointer]:
- /url: "#"
- generic [ref=e371]:
- img [ref=e373]
- generic [ref=e375]: Złóż zapytanie o rezerwację
- group "1 / 3" [ref=e376]:
- generic [ref=e380]:
- heading "Segment B" [level=3] [ref=e382]
- paragraph [ref=e384]:
- text: "Przykładowy model:"
- text: Toyota Yaris
- paragraph [ref=e386]: Od 79 zł brutto / doba
- link "Złóż zapytanie o rezerwację" [ref=e388] [cursor=pointer]:
- /url: "#"
- generic [ref=e389]:
- img [ref=e391]
- generic [ref=e393]: Złóż zapytanie o rezerwację
- group "2 / 3" [ref=e394]:
- generic [ref=e398]:
- heading "Segment LUX" [level=3] [ref=e400]
- paragraph [ref=e402]:
- text: "Przykładowy model:"
- text: Toyota Yaris
- paragraph [ref=e404]: Od 79 zł brutto / doba
- link "Złóż zapytanie o rezerwację" [ref=e406] [cursor=pointer]:
- /url: "#"
- generic [ref=e407]:
- img [ref=e409]
- generic [ref=e411]: Złóż zapytanie o rezerwację
- group "3 / 3" [ref=e412]:
- generic [ref=e416]:
- heading "Segment C/C+" [level=3] [ref=e418]
- paragraph [ref=e420]:
- text: "Przykładowy model:"
- text: Toyota Yaris
- paragraph [ref=e422]: Od 79 zł brutto / doba
- link "Złóż zapytanie o rezerwację" [ref=e424] [cursor=pointer]:
- /url: "#"
- generic [ref=e425]:
- img [ref=e427]
- generic [ref=e429]: Złóż zapytanie o rezerwację
- group [ref=e430]:
- generic [ref=e434]:
- heading [level=3] [ref=e436]: Segment B
- paragraph [ref=e438]: "Przykładowy model: Toyota Yaris"
- paragraph [ref=e440]: Od 79 zł brutto / doba
- link [ref=e442] [cursor=pointer]:
- /url: "#"
- generic [ref=e443]:
- img [ref=e445]
- generic [ref=e447]: Złóż zapytanie o rezerwację
- group [ref=e448]:
- generic [ref=e452]:
- heading [level=3] [ref=e454]: Segment LUX
- paragraph [ref=e456]: "Przykładowy model: Toyota Yaris"
- paragraph [ref=e458]: Od 79 zł brutto / doba
- link [ref=e460] [cursor=pointer]:
- /url: "#"
- generic [ref=e461]:
- img [ref=e463]
- generic [ref=e465]: Złóż zapytanie o rezerwację
- group [ref=e466]:
- generic [ref=e470]:
- heading [level=3] [ref=e472]: Segment C/C+
- paragraph [ref=e474]: "Przykładowy model: Toyota Yaris"
- paragraph [ref=e476]: Od 79 zł brutto / doba
- link [ref=e478] [cursor=pointer]:
- /url: "#"
- generic [ref=e479]:
- img [ref=e481]
- generic [ref=e483]: Złóż zapytanie o rezerwację
- button "Poprzedni slajd" [ref=e484] [cursor=pointer]:
- img [ref=e485]
- button "Następny slajd" [ref=e487] [cursor=pointer]:
- img [ref=e488]
- heading "Opinie o Carei." [level=2] [ref=e500]
- region "Carousel" [ref=e502]:
- generic [ref=e503]:
- group [ref=e504]:
- generic [ref=e506]:
- generic [ref=e507]:
- img [ref=e510]:
- generic [ref=e511]:
- img [ref=e513]
- img [ref=e516]
- generic [ref=e518]:
- img [ref=e520]
- img [ref=e523]
- generic [ref=e525]:
- img [ref=e527]
- img [ref=e530]
- generic [ref=e532]:
- img [ref=e534]
- img [ref=e537]
- generic [ref=e539]:
- img [ref=e541]
- img [ref=e544]
- link [ref=e547] [cursor=pointer]:
- /url: https://carei.pagedev.pl
- paragraph [ref=e549]:
- text: Lorem ipsum dolor sit amet consectetur. Id ut sit sed diam id lorem donec.
- strong [ref=e550]: Id eget felis enim
- text: ullamcorper dui adipiscing sed. Pharetra at egestas sed dignissim. Viverra ultrices id lacus eu ultricies commodo. Morbi ipsum purus est dolor. Luctus etiam mi nunc augue.
- generic [ref=e551]: Aneta W.
- group [ref=e552]:
- generic [ref=e554]:
- generic [ref=e555]:
- img [ref=e558]:
- generic [ref=e559]:
- img [ref=e561]
- img [ref=e564]
- generic [ref=e566]:
- img [ref=e568]
- img [ref=e571]
- generic [ref=e573]:
- img [ref=e575]
- img [ref=e578]
- generic [ref=e580]:
- img [ref=e582]
- img [ref=e585]
- generic [ref=e587]:
- img [ref=e589]
- img [ref=e592]
- link [ref=e595] [cursor=pointer]:
- /url: https://carei.pagedev.pl
- paragraph [ref=e597]:
- text: Lorem ipsum dolor sit amet consectetur. Id ut sit sed diam id lorem donec.
- strong [ref=e598]: Id eget felis enim
- text: ullamcorper dui adipiscing sed. Pharetra at egestas sed dignissim. Viverra ultrices id lacus eu ultricies commodo. Morbi ipsum purus est dolor. Luctus etiam mi nunc augue.
- generic [ref=e599]: Aneta W.
- group [ref=e600]:
- generic [ref=e602]:
- generic [ref=e603]:
- img [ref=e606]:
- generic [ref=e607]:
- img [ref=e609]
- img [ref=e612]
- generic [ref=e614]:
- img [ref=e616]
- img [ref=e619]
- generic [ref=e621]:
- img [ref=e623]
- img [ref=e626]
- generic [ref=e628]:
- img [ref=e630]
- img [ref=e633]
- generic [ref=e635]:
- img [ref=e637]
- img [ref=e640]
- link [ref=e643] [cursor=pointer]:
- /url: https://carei.pagedev.pl
- paragraph [ref=e645]:
- text: Lorem ipsum dolor sit amet consectetur. Id ut sit sed diam id lorem donec.
- strong [ref=e646]: Id eget felis enim
- text: ullamcorper dui adipiscing sed. Pharetra at egestas sed dignissim. Viverra ultrices id lacus eu ultricies commodo. Morbi ipsum purus est dolor. Luctus etiam mi nunc augue.
- generic [ref=e647]: Aneta W.
- group "1 / 4" [ref=e648]:
- generic [ref=e650]:
- generic [ref=e651]:
- img "Ocena 5 z 5" [ref=e654]:
- generic [ref=e655]:
- img [ref=e657]
- img [ref=e660]
- generic [ref=e662]:
- img [ref=e664]
- img [ref=e667]
- generic [ref=e669]:
- img [ref=e671]
- img [ref=e674]
- generic [ref=e676]:
- img [ref=e678]
- img [ref=e681]
- generic [ref=e683]:
- img [ref=e685]
- img [ref=e688]
- link [ref=e691] [cursor=pointer]:
- /url: https://carei.pagedev.pl
- paragraph [ref=e693]:
- text: Lorem ipsum dolor sit amet consectetur. Id ut sit sed diam id lorem donec.
- strong [ref=e694]: Id eget felis enim
- text: ullamcorper dui adipiscing sed. Pharetra at egestas sed dignissim. Viverra ultrices id lacus eu ultricies commodo. Morbi ipsum purus est dolor. Luctus etiam mi nunc augue.
- generic [ref=e695]: Aneta W.
- group "2 / 4" [ref=e696]:
- generic [ref=e698]:
- generic [ref=e699]:
- img "Ocena 5 z 5" [ref=e702]:
- generic [ref=e703]:
- img [ref=e705]
- img [ref=e708]
- generic [ref=e710]:
- img [ref=e712]
- img [ref=e715]
- generic [ref=e717]:
- img [ref=e719]
- img [ref=e722]
- generic [ref=e724]:
- img [ref=e726]
- img [ref=e729]
- generic [ref=e731]:
- img [ref=e733]
- img [ref=e736]
- link [ref=e739] [cursor=pointer]:
- /url: https://carei.pagedev.pl
- paragraph [ref=e741]:
- text: Lorem ipsum dolor sit amet consectetur. Id ut sit sed diam id lorem donec.
- strong [ref=e742]: Id eget felis enim
- text: ullamcorper dui adipiscing sed. Pharetra at egestas sed dignissim. Viverra ultrices id lacus eu ultricies commodo. Morbi ipsum purus est dolor. Luctus etiam mi nunc augue.
- generic [ref=e743]: Aneta W.
- group "3 / 4" [ref=e744]:
- generic [ref=e746]:
- generic [ref=e747]:
- img "Ocena 5 z 5" [ref=e750]:
- generic [ref=e751]:
- img [ref=e753]
- img [ref=e756]
- generic [ref=e758]:
- img [ref=e760]
- img [ref=e763]
- generic [ref=e765]:
- img [ref=e767]
- img [ref=e770]
- generic [ref=e772]:
- img [ref=e774]
- img [ref=e777]
- generic [ref=e779]:
- img [ref=e781]
- img [ref=e784]
- link [ref=e787] [cursor=pointer]:
- /url: https://carei.pagedev.pl
- paragraph [ref=e789]:
- text: Lorem ipsum dolor sit amet consectetur. Id ut sit sed diam id lorem donec.
- strong [ref=e790]: Id eget felis enim
- text: ullamcorper dui adipiscing sed. Pharetra at egestas sed dignissim. Viverra ultrices id lacus eu ultricies commodo. Morbi ipsum purus est dolor. Luctus etiam mi nunc augue.
- generic [ref=e791]: Aneta W.
- group [ref=e792]:
- generic [ref=e794]:
- generic [ref=e795]:
- img [ref=e798]:
- generic [ref=e799]:
- img [ref=e801]
- img [ref=e804]
- generic [ref=e806]:
- img [ref=e808]
- img [ref=e811]
- generic [ref=e813]:
- img [ref=e815]
- img [ref=e818]
- generic [ref=e820]:
- img [ref=e822]
- img [ref=e825]
- generic [ref=e827]:
- img [ref=e829]
- img [ref=e832]
- link [ref=e835] [cursor=pointer]:
- /url: https://carei.pagedev.pl
- paragraph [ref=e837]:
- text: Lorem ipsum dolor sit amet consectetur. Id ut sit sed diam id lorem donec.
- strong [ref=e838]: Id eget felis enim
- text: ullamcorper dui adipiscing sed. Pharetra at egestas sed dignissim. Viverra ultrices id lacus eu ultricies commodo. Morbi ipsum purus est dolor. Luctus etiam mi nunc augue.
- generic [ref=e839]: Aneta W.
- group [ref=e840]:
- generic [ref=e842]:
- generic [ref=e843]:
- img [ref=e846]:
- generic [ref=e847]:
- img [ref=e849]
- img [ref=e852]
- generic [ref=e854]:
- img [ref=e856]
- img [ref=e859]
- generic [ref=e861]:
- img [ref=e863]
- img [ref=e866]
- generic [ref=e868]:
- img [ref=e870]
- img [ref=e873]
- generic [ref=e875]:
- img [ref=e877]
- img [ref=e880]
- link [ref=e883] [cursor=pointer]:
- /url: https://carei.pagedev.pl
- paragraph [ref=e885]:
- text: Lorem ipsum dolor sit amet consectetur. Id ut sit sed diam id lorem donec.
- strong [ref=e886]: Id eget felis enim
- text: ullamcorper dui adipiscing sed. Pharetra at egestas sed dignissim. Viverra ultrices id lacus eu ultricies commodo. Morbi ipsum purus est dolor. Luctus etiam mi nunc augue.
- generic [ref=e887]: Aneta W.
- group [ref=e888]:
- generic [ref=e890]:
- generic [ref=e891]:
- img [ref=e894]:
- generic [ref=e895]:
- img [ref=e897]
- img [ref=e900]
- generic [ref=e902]:
- img [ref=e904]
- img [ref=e907]
- generic [ref=e909]:
- img [ref=e911]
- img [ref=e914]
- generic [ref=e916]:
- img [ref=e918]
- img [ref=e921]
- generic [ref=e923]:
- img [ref=e925]
- img [ref=e928]
- link [ref=e931] [cursor=pointer]:
- /url: https://carei.pagedev.pl
- paragraph [ref=e933]:
- text: Lorem ipsum dolor sit amet consectetur. Id ut sit sed diam id lorem donec.
- strong [ref=e934]: Id eget felis enim
- text: ullamcorper dui adipiscing sed. Pharetra at egestas sed dignissim. Viverra ultrices id lacus eu ultricies commodo. Morbi ipsum purus est dolor. Luctus etiam mi nunc augue.
- generic [ref=e935]: Aneta W.
- group [ref=e936]:
- generic [ref=e938]:
- generic [ref=e939]:
- img [ref=e942]:
- generic [ref=e943]:
- img [ref=e945]
- img [ref=e948]
- generic [ref=e950]:
- img [ref=e952]
- img [ref=e955]
- generic [ref=e957]:
- img [ref=e959]
- img [ref=e962]
- generic [ref=e964]:
- img [ref=e966]
- img [ref=e969]
- generic [ref=e971]:
- img [ref=e973]
- img [ref=e976]
- link [ref=e979] [cursor=pointer]:
- /url: https://carei.pagedev.pl
- paragraph [ref=e981]:
- text: Lorem ipsum dolor sit amet consectetur. Id ut sit sed diam id lorem donec.
- strong [ref=e982]: Id eget felis enim
- text: ullamcorper dui adipiscing sed. Pharetra at egestas sed dignissim. Viverra ultrices id lacus eu ultricies commodo. Morbi ipsum purus est dolor. Luctus etiam mi nunc augue.
- generic [ref=e983]: Aneta W.
- contentinfo [ref=e984]:
- generic [ref=e987]:
- heading "Szukasz więcej informacji?" [level=4] [ref=e989]
- heading "Skontaktuj się z naszą obsługą." [level=3] [ref=e994]:
- text: Skontaktuj się
- text: z naszą obsługą.
- generic [ref=e998]:
- generic [ref=e1000]:
- link "Assistance" [ref=e1002] [cursor=pointer]:
- /url: tel:+48572663614
- img [ref=e1003]
- generic [ref=e1007]:
- heading "Assistance" [level=3] [ref=e1008]:
- link "Assistance" [ref=e1009] [cursor=pointer]:
- /url: tel:+48572663614
- paragraph [ref=e1010]: +48 572 663 614
- generic [ref=e1012]:
- link "Biuro" [ref=e1014] [cursor=pointer]:
- /url: mailto:bok@carei.pl
- img [ref=e1015]
- generic [ref=e1021]:
- heading "Biuro" [level=3] [ref=e1022]:
- link "Biuro" [ref=e1023] [cursor=pointer]:
- /url: mailto:bok@carei.pl
- paragraph [ref=e1024]: bok@carei.pl
- generic [ref=e1035]:
- heading "Carei - Wypożyczalnia aut osobowych" [level=3] [ref=e1037]
- generic [ref=e1038]:
- paragraph [ref=e1040]:
- text: CAREI Sp. z o.o. Sp. k.
- text: ul. Solipska 1/U4,
- text: 02-482 Warszawa
- paragraph [ref=e1042]:
- text: "NIP: 527 249 90 39"
- text: "REGON: 140473129 KRS: 0000668452"
- generic [ref=e1050]:
- paragraph [ref=e1052]: Copyright © 2026 Carei
- paragraph [ref=e1054]: "Designed by: Kreatywny Brand"
- generic [ref=e1055]: laptop

View File

@@ -0,0 +1,587 @@
- generic [active] [ref=e1]:
- link "Przejdź do treści" [ref=e2] [cursor=pointer]:
- /url: "#content"
- banner [ref=e3]:
- generic [ref=e5]:
- link [ref=e7] [cursor=pointer]:
- /url: https://carei.pagedev.pl
- navigation "Menu" [ref=e9]:
- list [ref=e10]:
- listitem [ref=e11]:
- link "Wynajem długoterminowy" [ref=e12] [cursor=pointer]:
- /url: https://carei.pagedev.pl/wynajem-dlugoterminowy/
- listitem [ref=e13]:
- link "Wynajem krótkoterminowy" [ref=e14] [cursor=pointer]:
- /url: "#"
- listitem [ref=e15]:
- link "Kontakt" [ref=e16] [cursor=pointer]:
- /url: https://carei.pagedev.pl/kontakt/
- generic [ref=e18]:
- list [ref=e20]:
- listitem [ref=e21]:
- link "+48 572 663 614" [ref=e22] [cursor=pointer]:
- /url: tel:+48572663614
- img [ref=e24]
- generic [ref=e30]: +48 572 663 614
- generic [ref=e32]:
- button "Złóż zapytanie o rezerwację" [ref=e33] [cursor=pointer]:
- img [ref=e34]
- text: Złóż zapytanie o rezerwację
- option "Wybierz segment pojazdu" [disabled] [selected]
- option "Miejsce odbioru" [disabled] [selected]
- generic [ref=e39]:
- generic [ref=e41]:
- generic [ref=e42]:
- heading "Wypożyczalnia samochodów osobowych" [level=4] [ref=e44]
- heading "Wybierz segment i zacznij podróż." [level=2] [ref=e46]
- paragraph [ref=e48]:
- text: Otrzymaj auto w ciągu
- strong [ref=e49]: 1h
- text: od przyjęcia przez nas zlecenia.
- generic [ref=e53]:
- heading "Wypełnij formularz rezerwacji." [level=2] [ref=e54]
- generic [ref=e55]:
- generic [ref=e57]:
- combobox [ref=e58] [cursor=pointer]:
- option "Wybierz segment" [disabled] [selected]
- option "Segment B"
- option "Segment C"
- option "Segment C+"
- option "Segment D"
- option "Segment E"
- option "Segment LCV"
- option "Segment LUX"
- option "Segment P"
- option "Segment SUV"
- option "Segment SUV+"
- option "Segment VAN"
- img
- generic [ref=e59]:
- generic [ref=e61]:
- img
- generic: Od kiedy?
- textbox "Od kiedy?" [ref=e62]
- generic [ref=e64]:
- img
- generic: Do kiedy?
- textbox "Do kiedy?" [ref=e65]
- generic [ref=e67]:
- img
- combobox [disabled] [ref=e68] [cursor=pointer]:
- option "Najpierw wybierz segment" [disabled] [selected]
- img
- generic [ref=e70] [cursor=pointer]:
- checkbox "Zwrot w tej samej lokalizacji" [checked]
- img [ref=e72]
- generic [ref=e74]: Zwrot w tej samej lokalizacji
- button "Złóż zapytanie o rezerwację" [ref=e75] [cursor=pointer]:
- img [ref=e76]
- text: Złóż zapytanie o rezerwację
- generic [ref=e79]:
- generic [ref=e81]:
- img [ref=e84]
- generic [ref=e91]:
- heading "Szybka i dokładna obsługa zamówień" [level=3] [ref=e92]
- paragraph [ref=e93]: Gwarantujemy pełną gotowość auta na Twój przyjazd.
- generic [ref=e99]:
- img [ref=e102]
- generic [ref=e108]:
- heading "Bez opłat przygotowawczych" [level=3] [ref=e109]
- paragraph [ref=e110]: Stawiamy na jasne zasady, nie doliczamy ukrytych kosztów.
- generic [ref=e116]:
- img [ref=e119]
- generic [ref=e123]:
- heading "Atrakcyjne promocje weekendowe" [level=3] [ref=e124]
- paragraph [ref=e125]: Oszczędzaj na wynajmie planując weekendowy wyjazd.
- generic [ref=e127]:
- heading "Jak wypożyczyć auto krótkoterminowo?" [level=2] [ref=e132]
- paragraph [ref=e137]: Najszybciej i najprościej zrobić to z Carei w ciągu 1h od przyjęcia przez nas zlecenia otrzymasz już samochód.
- generic [ref=e142]:
- generic [ref=e145]:
- generic [ref=e146]:
- generic: "1."
- generic [ref=e147]:
- heading "Złóż zapytanie o rezerwację" [level=3] [ref=e148]
- paragraph [ref=e149]: W formularzu zaznacz jaka oferta Cię interesuje i podaj nam dane do kontaktu.
- generic [ref=e152]:
- generic [ref=e153]:
- generic: "2."
- generic [ref=e154]:
- heading "Skontaktuje się z Tobą obsługa klienta" [level=3] [ref=e155]
- paragraph [ref=e156]: Nasza infolinia działa 24h na dobę i przedstawi Ci konkretną propozycję
- generic [ref=e159]:
- generic [ref=e160]:
- generic: "3."
- generic [ref=e161]:
- heading "Odbierz kluczyki" [level=3] [ref=e162]
- paragraph [ref=e163]: Gwarantujemy minimum formalności przy odbiorze auta.
- link "Złóż zapytanie o rezerwację" [ref=e170] [cursor=pointer]:
- /url: "#"
- generic [ref=e171]:
- img [ref=e173]
- generic [ref=e175]: Złóż zapytanie o rezerwację
- generic [ref=e183]:
- heading "Chcesz wynająć auto na dłużej niż miesiąc?" [level=2] [ref=e185]
- paragraph [ref=e187]: Przygotujemy dla Ciebie atrakcyjne warunki wynajmu długoterminowego.
- link "Oferta najmu długoterminowego" [ref=e189] [cursor=pointer]:
- /url: "#"
- generic [ref=e191]: Oferta najmu długoterminowego
- generic [ref=e196]:
- img [ref=e201]
- generic [ref=e222]:
- heading "17 oddziałów w całej Polsce" [level=3] [ref=e224]:
- text: 17 oddziałów
- text: w całej Polsce
- heading "Podróżuj z Carei!" [level=2] [ref=e226]
- generic [ref=e227]:
- paragraph [ref=e228]: Od 2006 roku zajmujemy się szeroko rozumianym wynajmem samochodów osobowych na terenie Polski.
- paragraph [ref=e229]:
- text: W naszej ofercie znajdują się
- strong [ref=e230]: samochody standardowe oraz klasy premium
- text: .
- generic [ref=e233]:
- generic [ref=e234]: Białystok
- generic [ref=e235]: "|"
- generic [ref=e236]: Bydgoszcz
- generic [ref=e237]: "|"
- generic [ref=e238]: Gdańsk
- generic [ref=e239]: "|"
- generic [ref=e240]: Gorzów Wielkopolski
- generic [ref=e241]: "|"
- generic [ref=e242]: Katowice
- generic [ref=e243]: "|"
- generic [ref=e244]: Kielce
- generic [ref=e245]: "|"
- generic [ref=e246]: Kraków
- generic [ref=e247]: "|"
- generic [ref=e248]: Lublin
- generic [ref=e249]: "|"
- generic [ref=e250]: Olsztyn
- generic [ref=e251]: "|"
- generic [ref=e252]: Poznań
- generic [ref=e253]: "|"
- generic [ref=e254]: Radom
- generic [ref=e255]: "|"
- generic [ref=e256]: Rumia
- generic [ref=e257]: "|"
- generic [ref=e258]: Rzeszów
- generic [ref=e259]: "|"
- generic [ref=e260]: Sopot
- generic [ref=e261]: "|"
- generic [ref=e262]: Szczecin
- generic [ref=e263]: "|"
- generic [ref=e264]: Warszawa
- generic [ref=e265]: "|"
- generic [ref=e266]: Wrocław
- generic [ref=e267]: "|"
- generic [ref=e268]: Łódź
- generic [ref=e275]:
- heading "Wypożycz auto na swój wyjazd." [level=2] [ref=e277]
- paragraph [ref=e279]:
- text: Szybka obsługa zamówienia
- text: i minimum formalności.
- generic [ref=e280]:
- region "Carousel" [ref=e281]:
- generic [ref=e282]:
- group [ref=e283]:
- generic [ref=e287]:
- heading [level=3] [ref=e289]: Segment B
- paragraph [ref=e291]: "Przykładowy model: Toyota Yaris"
- paragraph [ref=e293]: Od 79 zł brutto / doba
- link [ref=e295] [cursor=pointer]:
- /url: "#"
- generic [ref=e296]:
- img [ref=e298]
- generic [ref=e300]: Złóż zapytanie o rezerwację
- group [ref=e301]:
- generic [ref=e305]:
- heading [level=3] [ref=e307]: Segment LUX
- paragraph [ref=e309]: "Przykładowy model: Toyota Yaris"
- paragraph [ref=e311]: Od 79 zł brutto / doba
- link [ref=e313] [cursor=pointer]:
- /url: "#"
- generic [ref=e314]:
- img [ref=e316]
- generic [ref=e318]: Złóż zapytanie o rezerwację
- group [ref=e319]:
- generic [ref=e323]:
- heading [level=3] [ref=e325]: Segment C/C+
- paragraph [ref=e327]: "Przykładowy model: Toyota Yaris"
- paragraph [ref=e329]: Od 79 zł brutto / doba
- link [ref=e331] [cursor=pointer]:
- /url: "#"
- generic [ref=e332]:
- img [ref=e334]
- generic [ref=e336]: Złóż zapytanie o rezerwację
- group "1 / 3" [ref=e337]:
- generic [ref=e341]:
- heading "Segment B" [level=3] [ref=e343]
- paragraph [ref=e345]:
- text: "Przykładowy model:"
- text: Toyota Yaris
- paragraph [ref=e347]: Od 79 zł brutto / doba
- link "Złóż zapytanie o rezerwację" [ref=e349] [cursor=pointer]:
- /url: "#"
- generic [ref=e350]:
- img [ref=e352]
- generic [ref=e354]: Złóż zapytanie o rezerwację
- group "2 / 3" [ref=e355]:
- generic [ref=e359]:
- heading "Segment LUX" [level=3] [ref=e361]
- paragraph [ref=e363]:
- text: "Przykładowy model:"
- text: Toyota Yaris
- paragraph [ref=e365]: Od 79 zł brutto / doba
- link "Złóż zapytanie o rezerwację" [ref=e367] [cursor=pointer]:
- /url: "#"
- generic [ref=e368]:
- img [ref=e370]
- generic [ref=e372]: Złóż zapytanie o rezerwację
- group "3 / 3" [ref=e373]:
- generic [ref=e377]:
- heading "Segment C/C+" [level=3] [ref=e379]
- paragraph [ref=e381]:
- text: "Przykładowy model:"
- text: Toyota Yaris
- paragraph [ref=e383]: Od 79 zł brutto / doba
- link "Złóż zapytanie o rezerwację" [ref=e385] [cursor=pointer]:
- /url: "#"
- generic [ref=e386]:
- img [ref=e388]
- generic [ref=e390]: Złóż zapytanie o rezerwację
- group [ref=e391]:
- generic [ref=e395]:
- heading [level=3] [ref=e397]: Segment B
- paragraph [ref=e399]: "Przykładowy model: Toyota Yaris"
- paragraph [ref=e401]: Od 79 zł brutto / doba
- link [ref=e403] [cursor=pointer]:
- /url: "#"
- generic [ref=e404]:
- img [ref=e406]
- generic [ref=e408]: Złóż zapytanie o rezerwację
- group [ref=e409]:
- generic [ref=e413]:
- heading [level=3] [ref=e415]: Segment LUX
- paragraph [ref=e417]: "Przykładowy model: Toyota Yaris"
- paragraph [ref=e419]: Od 79 zł brutto / doba
- link [ref=e421] [cursor=pointer]:
- /url: "#"
- generic [ref=e422]:
- img [ref=e424]
- generic [ref=e426]: Złóż zapytanie o rezerwację
- group [ref=e427]:
- generic [ref=e431]:
- heading [level=3] [ref=e433]: Segment C/C+
- paragraph [ref=e435]: "Przykładowy model: Toyota Yaris"
- paragraph [ref=e437]: Od 79 zł brutto / doba
- link [ref=e439] [cursor=pointer]:
- /url: "#"
- generic [ref=e440]:
- img [ref=e442]
- generic [ref=e444]: Złóż zapytanie o rezerwację
- button "Poprzedni slajd" [ref=e445] [cursor=pointer]:
- img [ref=e446]
- button "Następny slajd" [ref=e448] [cursor=pointer]:
- img [ref=e449]
- heading "Opinie o Carei." [level=2] [ref=e461]
- region "Carousel" [ref=e463]:
- generic [ref=e464]:
- group [ref=e465]:
- generic [ref=e467]:
- generic [ref=e468]:
- img [ref=e471]:
- generic [ref=e472]:
- img [ref=e474]
- img [ref=e477]
- generic [ref=e479]:
- img [ref=e481]
- img [ref=e484]
- generic [ref=e486]:
- img [ref=e488]
- img [ref=e491]
- generic [ref=e493]:
- img [ref=e495]
- img [ref=e498]
- generic [ref=e500]:
- img [ref=e502]
- img [ref=e505]
- link [ref=e508] [cursor=pointer]:
- /url: https://carei.pagedev.pl
- paragraph [ref=e510]:
- text: Lorem ipsum dolor sit amet consectetur. Id ut sit sed diam id lorem donec.
- strong [ref=e511]: Id eget felis enim
- text: ullamcorper dui adipiscing sed. Pharetra at egestas sed dignissim. Viverra ultrices id lacus eu ultricies commodo. Morbi ipsum purus est dolor. Luctus etiam mi nunc augue.
- generic [ref=e512]: Aneta W.
- group [ref=e513]:
- generic [ref=e515]:
- generic [ref=e516]:
- img [ref=e519]:
- generic [ref=e520]:
- img [ref=e522]
- img [ref=e525]
- generic [ref=e527]:
- img [ref=e529]
- img [ref=e532]
- generic [ref=e534]:
- img [ref=e536]
- img [ref=e539]
- generic [ref=e541]:
- img [ref=e543]
- img [ref=e546]
- generic [ref=e548]:
- img [ref=e550]
- img [ref=e553]
- link [ref=e556] [cursor=pointer]:
- /url: https://carei.pagedev.pl
- paragraph [ref=e558]:
- text: Lorem ipsum dolor sit amet consectetur. Id ut sit sed diam id lorem donec.
- strong [ref=e559]: Id eget felis enim
- text: ullamcorper dui adipiscing sed. Pharetra at egestas sed dignissim. Viverra ultrices id lacus eu ultricies commodo. Morbi ipsum purus est dolor. Luctus etiam mi nunc augue.
- generic [ref=e560]: Aneta W.
- group [ref=e561]:
- generic [ref=e563]:
- generic [ref=e564]:
- img [ref=e567]:
- generic [ref=e568]:
- img [ref=e570]
- img [ref=e573]
- generic [ref=e575]:
- img [ref=e577]
- img [ref=e580]
- generic [ref=e582]:
- img [ref=e584]
- img [ref=e587]
- generic [ref=e589]:
- img [ref=e591]
- img [ref=e594]
- generic [ref=e596]:
- img [ref=e598]
- img [ref=e601]
- link [ref=e604] [cursor=pointer]:
- /url: https://carei.pagedev.pl
- paragraph [ref=e606]:
- text: Lorem ipsum dolor sit amet consectetur. Id ut sit sed diam id lorem donec.
- strong [ref=e607]: Id eget felis enim
- text: ullamcorper dui adipiscing sed. Pharetra at egestas sed dignissim. Viverra ultrices id lacus eu ultricies commodo. Morbi ipsum purus est dolor. Luctus etiam mi nunc augue.
- generic [ref=e608]: Aneta W.
- group "1 / 4" [ref=e609]:
- generic [ref=e611]:
- generic [ref=e612]:
- img "Ocena 5 z 5" [ref=e615]:
- generic [ref=e616]:
- img [ref=e618]
- img [ref=e621]
- generic [ref=e623]:
- img [ref=e625]
- img [ref=e628]
- generic [ref=e630]:
- img [ref=e632]
- img [ref=e635]
- generic [ref=e637]:
- img [ref=e639]
- img [ref=e642]
- generic [ref=e644]:
- img [ref=e646]
- img [ref=e649]
- link [ref=e652] [cursor=pointer]:
- /url: https://carei.pagedev.pl
- paragraph [ref=e654]:
- text: Lorem ipsum dolor sit amet consectetur. Id ut sit sed diam id lorem donec.
- strong [ref=e655]: Id eget felis enim
- text: ullamcorper dui adipiscing sed. Pharetra at egestas sed dignissim. Viverra ultrices id lacus eu ultricies commodo. Morbi ipsum purus est dolor. Luctus etiam mi nunc augue.
- generic [ref=e656]: Aneta W.
- group "2 / 4" [ref=e657]:
- generic [ref=e659]:
- generic [ref=e660]:
- img "Ocena 5 z 5" [ref=e663]:
- generic [ref=e664]:
- img [ref=e666]
- img [ref=e669]
- generic [ref=e671]:
- img [ref=e673]
- img [ref=e676]
- generic [ref=e678]:
- img [ref=e680]
- img [ref=e683]
- generic [ref=e685]:
- img [ref=e687]
- img [ref=e690]
- generic [ref=e692]:
- img [ref=e694]
- img [ref=e697]
- link [ref=e700] [cursor=pointer]:
- /url: https://carei.pagedev.pl
- paragraph [ref=e702]:
- text: Lorem ipsum dolor sit amet consectetur. Id ut sit sed diam id lorem donec.
- strong [ref=e703]: Id eget felis enim
- text: ullamcorper dui adipiscing sed. Pharetra at egestas sed dignissim. Viverra ultrices id lacus eu ultricies commodo. Morbi ipsum purus est dolor. Luctus etiam mi nunc augue.
- generic [ref=e704]: Aneta W.
- group "3 / 4" [ref=e705]:
- generic [ref=e707]:
- generic [ref=e708]:
- img "Ocena 5 z 5" [ref=e711]:
- generic [ref=e712]:
- img [ref=e714]
- img [ref=e717]
- generic [ref=e719]:
- img [ref=e721]
- img [ref=e724]
- generic [ref=e726]:
- img [ref=e728]
- img [ref=e731]
- generic [ref=e733]:
- img [ref=e735]
- img [ref=e738]
- generic [ref=e740]:
- img [ref=e742]
- img [ref=e745]
- link [ref=e748] [cursor=pointer]:
- /url: https://carei.pagedev.pl
- paragraph [ref=e750]:
- text: Lorem ipsum dolor sit amet consectetur. Id ut sit sed diam id lorem donec.
- strong [ref=e751]: Id eget felis enim
- text: ullamcorper dui adipiscing sed. Pharetra at egestas sed dignissim. Viverra ultrices id lacus eu ultricies commodo. Morbi ipsum purus est dolor. Luctus etiam mi nunc augue.
- generic [ref=e752]: Aneta W.
- group [ref=e753]:
- generic [ref=e755]:
- generic [ref=e756]:
- img [ref=e759]:
- generic [ref=e760]:
- img [ref=e762]
- img [ref=e765]
- generic [ref=e767]:
- img [ref=e769]
- img [ref=e772]
- generic [ref=e774]:
- img [ref=e776]
- img [ref=e779]
- generic [ref=e781]:
- img [ref=e783]
- img [ref=e786]
- generic [ref=e788]:
- img [ref=e790]
- img [ref=e793]
- link [ref=e796] [cursor=pointer]:
- /url: https://carei.pagedev.pl
- paragraph [ref=e798]:
- text: Lorem ipsum dolor sit amet consectetur. Id ut sit sed diam id lorem donec.
- strong [ref=e799]: Id eget felis enim
- text: ullamcorper dui adipiscing sed. Pharetra at egestas sed dignissim. Viverra ultrices id lacus eu ultricies commodo. Morbi ipsum purus est dolor. Luctus etiam mi nunc augue.
- generic [ref=e800]: Aneta W.
- group [ref=e801]:
- generic [ref=e803]:
- generic [ref=e804]:
- img [ref=e807]:
- generic [ref=e808]:
- img [ref=e810]
- img [ref=e813]
- generic [ref=e815]:
- img [ref=e817]
- img [ref=e820]
- generic [ref=e822]:
- img [ref=e824]
- img [ref=e827]
- generic [ref=e829]:
- img [ref=e831]
- img [ref=e834]
- generic [ref=e836]:
- img [ref=e838]
- img [ref=e841]
- link [ref=e844] [cursor=pointer]:
- /url: https://carei.pagedev.pl
- paragraph [ref=e846]:
- text: Lorem ipsum dolor sit amet consectetur. Id ut sit sed diam id lorem donec.
- strong [ref=e847]: Id eget felis enim
- text: ullamcorper dui adipiscing sed. Pharetra at egestas sed dignissim. Viverra ultrices id lacus eu ultricies commodo. Morbi ipsum purus est dolor. Luctus etiam mi nunc augue.
- generic [ref=e848]: Aneta W.
- group [ref=e849]:
- generic [ref=e851]:
- generic [ref=e852]:
- img [ref=e855]:
- generic [ref=e856]:
- img [ref=e858]
- img [ref=e861]
- generic [ref=e863]:
- img [ref=e865]
- img [ref=e868]
- generic [ref=e870]:
- img [ref=e872]
- img [ref=e875]
- generic [ref=e877]:
- img [ref=e879]
- img [ref=e882]
- generic [ref=e884]:
- img [ref=e886]
- img [ref=e889]
- link [ref=e892] [cursor=pointer]:
- /url: https://carei.pagedev.pl
- paragraph [ref=e894]:
- text: Lorem ipsum dolor sit amet consectetur. Id ut sit sed diam id lorem donec.
- strong [ref=e895]: Id eget felis enim
- text: ullamcorper dui adipiscing sed. Pharetra at egestas sed dignissim. Viverra ultrices id lacus eu ultricies commodo. Morbi ipsum purus est dolor. Luctus etiam mi nunc augue.
- generic [ref=e896]: Aneta W.
- group [ref=e897]:
- generic [ref=e899]:
- generic [ref=e900]:
- img [ref=e903]:
- generic [ref=e904]:
- img [ref=e906]
- img [ref=e909]
- generic [ref=e911]:
- img [ref=e913]
- img [ref=e916]
- generic [ref=e918]:
- img [ref=e920]
- img [ref=e923]
- generic [ref=e925]:
- img [ref=e927]
- img [ref=e930]
- generic [ref=e932]:
- img [ref=e934]
- img [ref=e937]
- link [ref=e940] [cursor=pointer]:
- /url: https://carei.pagedev.pl
- paragraph [ref=e942]:
- text: Lorem ipsum dolor sit amet consectetur. Id ut sit sed diam id lorem donec.
- strong [ref=e943]: Id eget felis enim
- text: ullamcorper dui adipiscing sed. Pharetra at egestas sed dignissim. Viverra ultrices id lacus eu ultricies commodo. Morbi ipsum purus est dolor. Luctus etiam mi nunc augue.
- generic [ref=e944]: Aneta W.
- contentinfo [ref=e945]:
- generic [ref=e948]:
- heading "Szukasz więcej informacji?" [level=4] [ref=e950]
- heading "Skontaktuj się z naszą obsługą." [level=3] [ref=e955]:
- text: Skontaktuj się
- text: z naszą obsługą.
- generic [ref=e959]:
- generic [ref=e961]:
- link "Assistance" [ref=e963] [cursor=pointer]:
- /url: tel:+48572663614
- img [ref=e964]
- generic [ref=e968]:
- heading "Assistance" [level=3] [ref=e969]:
- link "Assistance" [ref=e970] [cursor=pointer]:
- /url: tel:+48572663614
- paragraph [ref=e971]: +48 572 663 614
- generic [ref=e973]:
- link "Biuro" [ref=e975] [cursor=pointer]:
- /url: mailto:bok@carei.pl
- img [ref=e976]
- generic [ref=e982]:
- heading "Biuro" [level=3] [ref=e983]:
- link "Biuro" [ref=e984] [cursor=pointer]:
- /url: mailto:bok@carei.pl
- paragraph [ref=e985]: bok@carei.pl
- generic [ref=e996]:
- heading "Carei - Wypożyczalnia aut osobowych" [level=3] [ref=e998]
- generic [ref=e999]:
- paragraph [ref=e1001]:
- text: CAREI Sp. z o.o. Sp. k.
- text: ul. Solipska 1/U4,
- text: 02-482 Warszawa
- paragraph [ref=e1003]:
- text: "NIP: 527 249 90 39"
- text: "REGON: 140473129 KRS: 0000668452"
- generic [ref=e1011]:
- paragraph [ref=e1013]: Copyright © 2026 Carei
- paragraph [ref=e1015]: "Designed by: Kreatywny Brand"
- generic [ref=e1016]: laptop

View File

@@ -31,37 +31,12 @@
"lmtime": 0, "lmtime": 0,
"modified": false "modified": false
}, },
".playwright-mcp": {},
"readme.html": { "readme.html": {
"type": "-", "type": "-",
"size": 7425, "size": 7425,
"lmtime": 0, "lmtime": 0,
"modified": false "modified": false
}, },
".serena": {
".gitignore": {
"type": "-",
"size": 28,
"lmtime": 1774382289791,
"modified": false
},
"memories": {},
"project.local.yml": {
"type": "-",
"size": 407,
"lmtime": 1774382289788,
"modified": false
},
"project.yml": {
"type": "-",
"size": 9594,
"lmtime": 1774382289785,
"modified": false
},
"cache": {
"php": {}
}
},
"softra-test.php": { "softra-test.php": {
"type": "-", "type": "-",
"size": 6081, "size": 6081,

BIN
carei-cities-current.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

BIN
carei-cities-section.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

BIN
carei-full-page.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

BIN
wp-admin/.DS_Store vendored

Binary file not shown.

BIN
wp-content/.DS_Store vendored

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1403,3 +1403,164 @@ button.carei-reservation-trigger:hover {
flex-direction: column; flex-direction: column;
} }
} }
/* ═══════════════════════════════════════════
Carei Map Widget
═══════════════════════════════════════════ */
.carei-map {
position: relative;
max-width: 520px;
width: 100%;
}
.carei-map__svg {
width: 100%;
height: auto;
display: block;
}
.carei-map__pin {
cursor: pointer;
transition: r 0.2s ease, fill 0.2s ease;
}
.carei-map__pin:hover,
.carei-map__pin--active {
r: 8;
}
.carei-map__tooltip {
position: absolute;
pointer-events: none;
z-index: 10;
transform: translate(-50%, -100%);
padding-bottom: 12px;
}
.carei-map__tooltip-content {
background: var(--carei-blue);
color: var(--carei-white);
font-family: var(--carei-font);
font-size: 13px;
line-height: 1.4;
padding: 10px 14px;
border-radius: var(--carei-radius);
white-space: pre-line;
min-width: 160px;
max-width: 260px;
text-align: center;
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
}
.carei-map__tooltip-content::after {
content: '';
position: absolute;
bottom: 4px;
left: 50%;
transform: translateX(-50%);
border: 6px solid transparent;
border-top-color: var(--carei-blue);
}
/* ═══════════════════════════════════════════
Carei Cities Widget
═══════════════════════════════════════════ */
.carei-cities {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
align-items: center;
gap: 6px 0;
font-family: var(--carei-font);
font-size: 15px;
font-weight: 500;
color: var(--carei-blue);
line-height: 2;
}
.carei-cities__item {
white-space: nowrap;
}
.carei-cities__item::after {
content: '|';
padding: 0 14px;
opacity: 0.35;
font-weight: 300;
display: inline-block;
}
.carei-cities__item:last-child::after {
display: none;
}
@media (max-width: 767px) {
.carei-cities {
font-size: 13px;
gap: 4px 0;
}
.carei-cities__item::after {
padding: 0 8px;
}
}
/* ═══════════════════════════════════════════
Carei Branches Widget
═══════════════════════════════════════════ */
.carei-branches {
display: grid;
grid-template-columns: repeat(5, 1fr);
font-family: var(--carei-font);
color: var(--carei-white);
}
.carei-branches__item {
padding: 24px 16px;
text-align: center;
border-top: 1px solid rgba(255, 255, 255, 0.15);
}
.carei-branches__name {
font-size: 16px;
font-weight: 700;
margin-bottom: 6px;
}
.carei-branches__street,
.carei-branches__zip-city {
font-size: 14px;
font-weight: 400;
line-height: 1.5;
opacity: 0.85;
}
@media (max-width: 1024px) {
.carei-branches {
grid-template-columns: repeat(3, 1fr);
}
}
@media (max-width: 767px) {
.carei-branches {
grid-template-columns: repeat(2, 1fr);
}
.carei-branches__item {
padding: 18px 12px;
}
.carei-branches__name {
font-size: 14px;
}
.carei-branches__street,
.carei-branches__zip-city {
font-size: 13px;
}
}
@media (max-width: 480px) {
.carei-branches {
grid-template-columns: 1fr;
}
}

View File

@@ -1265,6 +1265,110 @@
initClearErrors(); initClearErrors();
initAbroad(); initAbroad();
initSubmit(); initSubmit();
initMap();
}
/* ═══════════════════════════════════════════
Carei Map — dynamic pins & tooltips
═══════════════════════════════════════════ */
function initMap() {
var mapEl = document.querySelector('.carei-map');
if (!mapEl) return;
var pins;
try {
pins = JSON.parse(mapEl.getAttribute('data-pins') || '[]');
} catch (e) {
return;
}
if (!pins.length) return;
var svg = mapEl.querySelector('.carei-map__svg');
var pinsGroup = svg.querySelector('.carei-map__pins');
var tooltip = mapEl.querySelector('.carei-map__tooltip');
var tooltipContent = mapEl.querySelector('.carei-map__tooltip-content');
if (!svg || !pinsGroup || !tooltip || !tooltipContent) return;
var activePin = null;
var SVG_NS = 'http://www.w3.org/2000/svg';
pins.forEach(function (pin) {
var circle = document.createElementNS(SVG_NS, 'circle');
circle.setAttribute('cx', pin.x);
circle.setAttribute('cy', pin.y);
circle.setAttribute('r', '6');
circle.setAttribute('fill', '#FF0000');
circle.setAttribute('class', 'carei-map__pin');
circle.setAttribute('data-city', pin.city);
circle.setAttribute('data-address', pin.address || '');
circle.addEventListener('mouseenter', function () {
showTooltip(pin, circle);
});
circle.addEventListener('mouseleave', function () {
if (activePin !== circle) {
hideTooltip();
}
});
circle.addEventListener('click', function (e) {
e.stopPropagation();
if (activePin === circle) {
activePin = null;
circle.classList.remove('carei-map__pin--active');
hideTooltip();
} else {
if (activePin) activePin.classList.remove('carei-map__pin--active');
activePin = circle;
circle.classList.add('carei-map__pin--active');
showTooltip(pin, circle);
}
});
pinsGroup.appendChild(circle);
});
// Click outside closes tooltip
document.addEventListener('click', function () {
if (activePin) {
activePin.classList.remove('carei-map__pin--active');
activePin = null;
hideTooltip();
}
});
function showTooltip(pin, circle) {
// Build tooltip text: address lines + bold city
var addr = pin.address || '';
var lines = addr ? addr.replace(/\\n/g, '\n') : pin.city;
tooltipContent.textContent = '';
// If address has postal code, format nicely
if (addr) {
tooltipContent.innerHTML = addr.replace(/\n/g, '<br>');
} else {
tooltipContent.textContent = pin.city;
}
// Position tooltip relative to map container
var svgRect = svg.getBoundingClientRect();
var mapRect = mapEl.getBoundingClientRect();
var svgWidth = svg.viewBox.baseVal.width || 600;
var svgHeight = svg.viewBox.baseVal.height || 570;
var scaleX = svgRect.width / svgWidth;
var scaleY = svgRect.height / svgHeight;
var left = (svgRect.left - mapRect.left) + pin.x * scaleX;
var top = (svgRect.top - mapRect.top) + pin.y * scaleY;
tooltip.style.display = 'block';
tooltip.style.left = left + 'px';
tooltip.style.top = top + 'px';
}
function hideTooltip() {
tooltip.style.display = 'none';
}
} }
if (document.readyState === 'loading') { if (document.readyState === 'loading') {

View File

@@ -88,6 +88,15 @@ add_action( 'elementor/widgets/register', function ( $widgets_manager ) {
require_once CAREI_RESERVATION_PATH . 'includes/class-search-widget.php'; require_once CAREI_RESERVATION_PATH . 'includes/class-search-widget.php';
$widgets_manager->register( new Carei_Search_Widget() ); $widgets_manager->register( new Carei_Search_Widget() );
require_once CAREI_RESERVATION_PATH . 'includes/class-map-widget.php';
$widgets_manager->register( new Carei_Map_Widget() );
require_once CAREI_RESERVATION_PATH . 'includes/class-cities-widget.php';
$widgets_manager->register( new Carei_Cities_Widget() );
require_once CAREI_RESERVATION_PATH . 'includes/class-branches-widget.php';
$widgets_manager->register( new Carei_Branches_Widget() );
} ); } );
/** /**

View File

@@ -0,0 +1,133 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Elementor Widget: Carei Branches — grid oddziałów z adresami.
*/
class Carei_Branches_Widget extends \Elementor\Widget_Base {
const NAME_FIXES = array(
'BYDGOSZC' => 'BYDGOSZCZ',
'GORZÓW WIE' => 'GORZÓW WIELKOPOLSKI',
'RZSZÓW' => 'RZESZÓW',
'SK-KAM' => '',
);
public function get_name() {
return 'carei-branches';
}
public function get_title() {
return 'Carei Branches';
}
public function get_icon() {
return 'eicon-posts-grid';
}
public function get_categories() {
return array( 'general' );
}
public function get_style_depends() {
return array( 'carei-reservation-css' );
}
protected function register_controls() {}
/**
* Clean branch name and return base city.
*/
private static function clean_name( $raw ) {
$name = trim( $raw );
$name = preg_replace( '/\s+[DL]$/u', '', $name );
if ( isset( self::NAME_FIXES[ $name ] ) ) {
$name = self::NAME_FIXES[ $name ];
}
if ( empty( $name ) || preg_match( '/^[A-Z]{2,4}-[A-Z]{2,4}$/u', $name ) ) {
return '';
}
return $name;
}
/**
* Get unique branches with addresses.
*/
private function get_branches_data() {
$api = Carei_Softra_API::get_instance();
if ( null === $api ) {
return array();
}
$branches = $api->get_branches_cached();
if ( is_wp_error( $branches ) || ! is_array( $branches ) ) {
return array();
}
$result = array();
$seen = array();
foreach ( $branches as $b ) {
$raw_name = isset( $b['name'] ) ? $b['name'] : '';
$city = self::clean_name( $raw_name );
if ( empty( $city ) ) {
continue;
}
$norm = mb_strtolower( $city, 'UTF-8' );
if ( isset( $seen[ $norm ] ) ) {
continue;
}
$seen[ $norm ] = true;
$display_city = mb_convert_case( $city, MB_CASE_TITLE, 'UTF-8' );
$street = isset( $b['street'] ) ? trim( $b['street'] ) : '';
$zip = isset( $b['zipCode'] ) ? trim( (string) $b['zipCode'] ) : '';
$api_city = isset( $b['city'] ) ? trim( $b['city'] ) : '';
$api_city_tc = mb_convert_case( $api_city, MB_CASE_TITLE, 'UTF-8' );
// Format street
if ( $street ) {
$street_lower = mb_strtolower( $street, 'UTF-8' );
$has_prefix = preg_match( '/^(ul\.|al\.|pl\.|os\.)/u', $street_lower );
$street = $has_prefix ? $street : 'ul. ' . $street;
}
$result[] = array(
'name' => 'Oddział ' . $display_city,
'street' => $street,
'zipCity' => trim( $zip . ' ' . $api_city_tc ),
);
}
usort( $result, function ( $a, $b ) {
return strcmp( $a['name'], $b['name'] );
} );
return $result;
}
protected function render() {
$branches = $this->get_branches_data();
if ( empty( $branches ) ) {
return;
}
?>
<div class="carei-branches">
<?php foreach ( $branches as $branch ) : ?>
<div class="carei-branches__item">
<div class="carei-branches__name"><?php echo esc_html( $branch['name'] ); ?></div>
<?php if ( $branch['street'] ) : ?>
<div class="carei-branches__street"><?php echo esc_html( $branch['street'] ); ?></div>
<?php endif; ?>
<?php if ( $branch['zipCity'] ) : ?>
<div class="carei-branches__zip-city"><?php echo esc_html( $branch['zipCity'] ); ?></div>
<?php endif; ?>
</div>
<?php endforeach; ?>
</div>
<?php
}
}

View File

@@ -0,0 +1,120 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Elementor Widget: Carei Cities — siatka miast oddziałów.
*/
class Carei_Cities_Widget extends \Elementor\Widget_Base {
public function get_name() {
return 'carei-cities';
}
public function get_title() {
return 'Carei Cities';
}
public function get_icon() {
return 'eicon-bullet-list';
}
public function get_categories() {
return array( 'general' );
}
public function get_style_depends() {
return array( 'carei-reservation-css' );
}
public function get_script_depends() {
return array( 'carei-reservation-js' );
}
protected function register_controls() {}
/**
* Truncated / misspelled names from Softra API → correct full city names.
*/
const NAME_FIXES = array(
'BYDGOSZC' => 'BYDGOSZCZ',
'GORZÓW WIE' => 'GORZÓW WIELKOPOLSKI',
'RZSZÓW' => 'RZESZÓW',
'SK-KAM' => '',
);
/**
* Clean branch name: handle D(Dworzec)/L suffixes, fix truncated names, title-case.
* API returns names like "GDAŃSK D", "GDAŃSK L", "BYDGOSZC D", "SK-KAM", "GORZÓW WIE".
* D-suffix branches without a base variant → "Oddział [City]".
*/
private static function clean_city_name( $raw ) {
$name = trim( $raw );
// Detect D (Dworzec) suffix before stripping
$is_dworzec = (bool) preg_match( '/\s+D$/u', $name );
// Strip trailing single-letter suffixes (D=Dworzec, L=Lotnisko/inne)
$name = preg_replace( '/\s+[DL]$/u', '', $name );
// Fix known truncated/misspelled names
if ( isset( self::NAME_FIXES[ $name ] ) ) {
$name = self::NAME_FIXES[ $name ];
}
// Skip empty or non-city codes
if ( empty( $name ) || preg_match( '/^[A-Z]{2,4}-[A-Z]{2,4}$/u', $name ) ) {
return '';
}
// Title-case: "GDAŃSK" → "Gdańsk"
$name = mb_convert_case( $name, MB_CASE_TITLE, 'UTF-8' );
return $name;
}
/**
* Extract unique city names from branches.
*/
private function get_city_names() {
$api = Carei_Softra_API::get_instance();
if ( null === $api ) {
return array();
}
$branches = $api->get_branches_cached();
if ( is_wp_error( $branches ) || ! is_array( $branches ) ) {
return array();
}
$cities = array();
$seen = array();
foreach ( $branches as $b ) {
$name = isset( $b['name'] ) ? $b['name'] : '';
$city = self::clean_city_name( $name );
if ( empty( $city ) ) {
continue;
}
$norm = mb_strtolower( $city, 'UTF-8' );
if ( isset( $seen[ $norm ] ) ) {
continue;
}
$seen[ $norm ] = true;
$cities[] = $city;
}
sort( $cities );
return $cities;
}
protected function render() {
$cities = $this->get_city_names();
if ( empty( $cities ) ) {
return;
}
?>
<div class="carei-cities">
<?php foreach ( $cities as $i => $city ) : ?>
<span class="carei-cities__item"><?php echo esc_html( $city ); ?></span>
<?php endforeach; ?>
</div>
<?php
}
}

File diff suppressed because one or more lines are too long

View File

@@ -117,6 +117,13 @@ class Carei_REST_Proxy {
), ),
) ); ) );
// GET /branches-full (cached, full branch objects with descriptions)
register_rest_route( self::NAMESPACE, '/branches-full', array(
'methods' => 'GET',
'callback' => array( $this, 'get_branches_full' ),
'permission_callback' => '__return_true',
) );
// GET /agreements // GET /agreements
register_rest_route( self::NAMESPACE, '/agreements', array( register_rest_route( self::NAMESPACE, '/agreements', array(
'methods' => 'GET', 'methods' => 'GET',
@@ -276,6 +283,14 @@ class Carei_REST_Proxy {
) ); ) );
} }
public function get_branches_full( WP_REST_Request $request ) {
$api = $this->api();
if ( is_wp_error( $api ) ) {
return $api;
}
return $this->respond( $api->get_branches_cached() );
}
public function get_agreements( WP_REST_Request $request ) { public function get_agreements( WP_REST_Request $request ) {
$api = $this->api(); $api = $this->api();
if ( is_wp_error( $api ) ) { if ( is_wp_error( $api ) ) {

View File

@@ -153,6 +153,26 @@ class Carei_Softra_API {
return $this->request( 'GET', '/branch/list' ); return $this->request( 'GET', '/branch/list' );
} }
/**
* Get branches with 60-min transient cache.
*/
public function get_branches_cached() {
$cache_key = 'carei_branches_list';
$cached = get_transient( $cache_key );
if ( false !== $cached ) {
return $cached;
}
$branches = $this->get_branches();
if ( is_wp_error( $branches ) || ! is_array( $branches ) ) {
return is_wp_error( $branches ) ? $branches : array();
}
set_transient( $cache_key, $branches, HOUR_IN_SECONDS );
return $branches;
}
public function get_all_car_classes() { public function get_all_car_classes() {
return $this->request( 'GET', '/car/class/listAll' ); return $this->request( 'GET', '/car/class/listAll' );
} }
@@ -170,7 +190,7 @@ class Carei_Softra_API {
return $cached; return $cached;
} }
$branches = $this->get_branches(); $branches = $this->get_branches_cached();
if ( is_wp_error( $branches ) || ! is_array( $branches ) ) { if ( is_wp_error( $branches ) || ! is_array( $branches ) ) {
return is_wp_error( $branches ) ? $branches : array(); return is_wp_error( $branches ) ? $branches : array();
} }

Binary file not shown.

BIN
wp-includes/.DS_Store vendored

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.