--- 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 `` 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 `` 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*