---
phase: 13-protection-packages
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
  - wp-content/plugins/carei-reservation/assets/js/carei-reservation.js
  - wp-content/plugins/carei-reservation/assets/css/carei-reservation.css
  - wp-content/plugins/carei-reservation/includes/class-elementor-widget.php
autonomous: false
delegation: off
---

<objective>
## Goal
Wyświetlanie pakietów ochronnych SOFT i PREMIUM jako dedykowanych kafelków z ceną obliczaną dynamicznie na podstawie liczby dni wynajmu (3 progi cenowe: minimalna 1-3 dni, za dobę 4-15 dni, maksymalna 16+ dni).

## Purpose
Klient chce prezentować pakiety ochronne w zrozumiały sposób — zamiast generycznego "od X do Y zł" użytkownik widzi jedną konkretną cenę dopasowaną do długości jego rezerwacji. Wybór pakietu jest opcjonalny i wzajemnie wykluczający (SOFT lub PREMIUM, nie oba).

## Output
- Sekcja "Pakiety ochronne" z dwoma kafelkami (SOFT, PREMIUM) z dynamiczną ceną
- Cena przeliczana automatycznie przy zmianie dat
- Wybrany pakiet uwzględniany w podsumowaniu i booking submission
</objective>

<context>
## Project Context
@.paul/PROJECT.md
@.paul/ROADMAP.md
@.paul/STATE.md

## Source Files
@wp-content/plugins/carei-reservation/assets/js/carei-reservation.js
@wp-content/plugins/carei-reservation/assets/css/carei-reservation.css
@wp-content/plugins/carei-reservation/includes/class-elementor-widget.php
</context>

<skills>
No SPECIAL-FLOWS.md — skills section omitted.
</skills>

<acceptance_criteria>

## AC-1: Tiered price calculation
```gherkin
Given insurance items from API with minPrice, price (per day), and maxPrice
When the user has selected rental dates spanning N days
Then each protection package shows:
  - minPrice (flat) when N <= 3
  - price × N when 4 <= N <= 15
  - maxPrice (flat) when N > 15
```

## AC-2: Mutually exclusive selection
```gherkin
Given two protection package cards (SOFT, PREMIUM) are displayed
When the user clicks on one package
Then the other package is deselected (radio behavior)
And the user can also deselect to choose no package
```

## AC-3: Dynamic price update on date change
```gherkin
Given protection packages are displayed with calculated prices
When the user changes pickup or return date
Then the prices on both cards recalculate immediately
And the correct tier (flat/per-day/flat) is applied based on new duration
```

## AC-4: Package included in booking submission
```gherkin
Given the user has selected a protection package (SOFT or PREMIUM)
When the booking is submitted
Then the selected package is included in priceItems with correct calculated price
And the package appears in the summary overlay with its name and total price
```

</acceptance_criteria>

<tasks>

<task type="auto">
  <name>Task 1: Render protection packages as radio-style cards with tiered pricing</name>
  <files>wp-content/plugins/carei-reservation/assets/js/carei-reservation.js, wp-content/plugins/carei-reservation/assets/css/carei-reservation.css</files>
  <action>
    1. In the pricelist loading section (~line 432-458), after filtering insuranceItems:
       - Create a new function `buildProtectionCard(item, days)` that:
         - Calculates price based on days: `days <= 3` → item.minPrice, `days >= 4 && days <= 15` → item.price * days, `days > 15` → item.maxPrice
         - Renders a card with radio behavior (use checkbox with JS toggle for deselect capability)
         - Shows price label: "180 zł" (flat) or "60 zł/doba = 420 zł" (per-day with total)
         - Card design: prominent tile with package name, price, and a brief description if available from API
       - Replace current `insuranceContainer` rendering: instead of `buildExtraCard` for each item, use `buildProtectionCard`
       - Use `name="protection"` with type="radio" BUT wrap in a click handler that allows deselection (click selected = deselect)

    2. Add function `updateProtectionPrices()` that:
       - Reads current days count from the date fields (reuse existing daysCount logic)
       - Recalculates prices for both cards
       - Updates the displayed price labels
       - Call this function when dates change (hook into existing date change handler)

    3. CSS for protection cards in carei-reservation.css:
       - Two cards side by side (flex row, gap)
       - Active/selected state with border highlight (#2F2482)
       - Responsive: stack vertically on mobile
       - Style consistent with existing extra cards but visually distinct (larger, more prominent)

    Avoid: Changing the existing `buildExtraCard` function — it still serves regular extras.
    Avoid: Hardcoding prices — all pricing comes from API item fields (minPrice, price, maxPrice).
  </action>
  <verify>
    - Open reservation form, select dates for 2 days → packages show flat minPrice
    - Change dates to 7 days → packages show per-day price × 7
    - Change dates to 20 days → packages show flat maxPrice
    - Click SOFT → SOFT selected, click PREMIUM → SOFT deselected + PREMIUM selected
    - Click selected card again → deselected (no package chosen)
  </verify>
  <done>AC-1, AC-2, AC-3 satisfied: Protection packages render with correct tiered pricing, mutually exclusive selection, and dynamic price updates</done>
</task>

<task type="auto">
  <name>Task 2: Wire protection package into booking submission and summary</name>
  <files>wp-content/plugins/carei-reservation/assets/js/carei-reservation.js</files>
  <action>
    1. In the booking submission logic (where extras[] checkboxes are collected):
       - Add collection of selected protection package: query `input[name="protection"]:checked`
       - Build priceItem with: id, name, unit='szt.', amount=1, priceBeforeDiscount = calculated total price, discount=0, priceAfterDiscount = same
       - Append to the priceItems array sent to API

    2. In the summary overlay rendering:
       - Add a row for the selected protection package showing package name and total price
       - If no package selected, don't show a row

    3. Ensure the protection price is included in the total calculation in the summary.

    Avoid: Changing the admin panel storage logic — protection items go through as regular priceItems, same as extras.
    Avoid: Duplicating protection item if it also appears in extras — ensure the filtering separates them cleanly.
  </action>
  <verify>
    - Select SOFT package + submit → summary shows "Pakiet ochrony Soft — XXX zł"
    - Submit without package → no protection row in summary
    - Full booking flow completes with package included in API call
  </verify>
  <done>AC-4 satisfied: Selected package included in booking submission and visible in summary</done>
</task>

<task type="checkpoint:human-verify" gate="blocking">
  <what-built>Protection package cards with tiered pricing, radio selection, date-driven recalculation, and booking integration</what-built>
  <how-to-verify>
    1. Otwórz stronę carei.pagedev.pl i kliknij rezerwację
    2. Wybierz segment, lokalizację i daty na 2 dni → sprawdź cenę pakietów (powinna być cena minimalna)
    3. Zmień daty na 7 dni → cena powinna się przeliczyć (cena za dobę × 7)
    4. Zmień daty na 20 dni → cena powinna być stała (maksymalna)
    5. Kliknij SOFT → zaznaczony, kliknij PREMIUM → SOFT odznaczony, PREMIUM zaznaczony
    6. Kliknij zaznaczony ponownie → odznaczony (brak pakietu)
    7. Wybierz pakiet i przejdź do podsumowania → pakiet widoczny z ceną
    8. Sprawdź na mobile → karty jedna pod drugą
  </how-to-verify>
  <resume-signal>Type "approved" to continue, or describe issues to fix</resume-signal>
</task>

</tasks>

<boundaries>

## DO NOT CHANGE
- class-rest-proxy.php (API proxy unchanged — data comes from existing pricelist endpoint)
- class-admin-panel.php (admin storage — protection items stored same as extras via priceItems)
- class-softra-api.php (Softra API client — no changes needed)
- Abroad section logic (wyjazd zagraniczny)
- Hero search form widget

## SCOPE LIMITS
- No new API endpoints — protection packages come from existing pricelist/additionalItems
- No backend pricing logic — all tier calculation is client-side based on API item fields
- No new admin UI for managing packages — data managed in Softra system
- Description/zakres usług text comes from API item.description — no hardcoded descriptions

</boundaries>

<verification>
Before declaring plan complete:
- [ ] Protection packages display with correct tiered pricing for all 3 duration ranges
- [ ] Selection is mutually exclusive with deselect capability
- [ ] Prices recalculate on date change
- [ ] Selected package included in booking submission priceItems
- [ ] Summary overlay shows selected package with price
- [ ] No regressions in existing extras or abroad sections
- [ ] Responsive layout works on mobile
- [ ] All acceptance criteria met
</verification>

<success_criteria>
- All tasks completed
- All verification checks pass
- No errors or warnings introduced
- Protection packages display correctly for all 3 pricing tiers
- Booking flow works end-to-end with selected package
</success_criteria>

<output>
After completion, create `.paul/phases/13-protection-packages/13-01-SUMMARY.md`
</output>
