---
phase: 100-preset-scope-print-ux
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
  - resources/views/shipments/prepare.php
  - resources/views/orders/show.php
  - src/Modules/Printing/PrintApiController.php
  - src/Modules/Printing/PrintJobRepository.php
  - routes/web.php
autonomous: true
delegation: off
---

<objective>
## Goal
Zawezic dzialanie presetow przesylek do wymiarow+wagi oraz poprawic UX przycisku "Drukuj" po utworzeniu przesylki: auto-klikniecie ostatniej etykiety, polling kolejki wydruku, usuniecie zbednego "-".

## Purpose
Presety sa uzywane do szybkiego wypelniania parametrow paczki dla tego samego typu produktu, natomiast przewoznik/serwis zazwyczaj zalezy od konkretnego zamowienia — obecne nadpisywanie carrier/delivery wywoluje pomylki. Przycisk "W kolejce" nie resetuje sie nawet po wydrukowaniu etykiety, co wymaga recznego odswiezania strony i utrudnia kolejne nadania.

## Output
- applyPreset() w prepare.php zawezone do package_type/length/width/height/weight
- Auto-click na przycisku "Drukuj" dla ostatniej (najnowszej) etykiety po utworzeniu przesylki
- Polling statusu print_jobs w orders/show.php i prepare.php (GET /api/print/jobs/status)
- Usuniecie placeholderu "-" przed przyciskiem Drukuj
</objective>

<context>
@.paul/PROJECT.md
@.paul/STATE.md
@resources/views/shipments/prepare.php
@resources/views/orders/show.php
@src/Modules/Printing/PrintApiController.php
@src/Modules/Printing/PrintJobRepository.php
@routes/web.php
</context>

<acceptance_criteria>

## AC-1: Preset zmienia tylko paczke
```gherkin
Given formularz /shipments/prepare z wybranym przewoznikiem X i serwisem Y
When uzytkownik klika preset P ktory w bazie ma inny carrier/delivery_method
Then carrier pozostaje X, serwis Y pozostaje wybrany
And pola package_type, length_cm, width_cm, height_cm, weight_kg sa nadpisane wartosciami z presetu
And formularz jest nadal auto-submitowany po autofill (zachowanie Phase 78)
```

## AC-2: Auto-click ostatniej etykiety
```gherkin
Given zamowienie z pakietami P1,P2 (P2 ma status label_ready i jest najnowszy)
When uzytkownik tworzy nowa przesylke P3 i widok /orders/{id} ladowany jest ponownie z aktywna zakladka przesylki
Then po zaladowaniu strony automatycznie uruchamiany jest click na btn-print-label dla P3 (najnowsza pozycja)
And wysylane jest POST /api/print/jobs dla P3
And przycisk P3 przechodzi w stan "W kolejce"
```

## AC-3: Polling kolejki wydruku
```gherkin
Given przycisk Drukuj dla paczki X w stanie "W kolejce" (print_job status=pending)
When agent drukarki oznaczy job jako completed (print_job status=completed)
Then nie pozniej niz 10 sekund od oznaczenia przycisk X wraca do etykiety "Drukuj"
And przycisk odzyskuje klase btn--secondary i jest aktywny
And gdy brak aktywnych wpisow pending dla widoku, polling sie zatrzymuje
```

## AC-4: Brak placeholdera "-"
```gherkin
Given widok /orders/{id} lub /shipments/prepare dla paczki bez pliku etykiety lub w stanie przejsciowym
When tabela przesylek jest renderowana
Then w komorce etykiety nie pojawia sie znak "-" przed przyciskiem Drukuj
And puste stany pokazuja jedynie sam przycisk Drukuj (lub brak dla is-manual)
```

</acceptance_criteria>

<tasks>

<task type="auto">
  <name>Task 1: Zawezic applyPreset() i usunac placeholder "-"</name>
  <files>resources/views/shipments/prepare.php, resources/views/orders/show.php</files>
  <action>
    W resources/views/shipments/prepare.php, funkcja applyPreset() (ok. linii 957-999):
    - Usun caly blok ustawiajacy carrierSelect, hiddenInput, credentialsInput, carrierInput, providerInput i wywolanie _syncTrigger + dispatch change.
    - Usun setTimeout() 200ms (juz niepotrzebny — nie zmieniamy carrier).
    - Usun wywolanie selectDeliveryService(preset); funkcja selectDeliveryService moze zostac w pliku jesli uzywana gdzie indziej, ale nie jest wywolywana z applyPreset.
    - Zostaw wywolania setFieldValue() dla: package_type, length_cm, width_cm, height_cm, weight_kg.
    - USUN wywolania setFieldValue() dla sender_point_id i label_format — nalezy do "formy dostawy".
    - Zostaw auto-submit formularza po autofill (zachowanie Phase 78) — ma sie odpalac bezposrednio po setFieldValue() z krotkim opoznieniem 100 ms.

    W resources/views/shipments/prepare.php usun placeholder "-" w kolumnie etykiety (ok. linii 415-417):
    - Usun gale `<?php else: ?> - <?php endif; ?>` (zachowujac przypadek "Generowanie etykiety...").

    W resources/views/orders/show.php usun placeholder "-" przed przyciskiem Drukuj (ok. linii 580-582):
    - Usun caly `<?php elseif ($pkgStatus !== 'error'): ?> - <?php endif; ?>` (pobierz zostaje bez fallbacku).

    Avoid: modyfikacji form samych presetow CRUD (Settings) — zakres to tylko autofill. Nie dotykaj selectDeliveryService() jesli uzywane poza applyPreset — usuniecie wywolania wystarczy.
  </action>
  <verify>
    1. Otworz /shipments/prepare?orderId=X, wybierz carrier A + serwis a1, kliknij preset z carrier B
    2. Potwierdz ze carrier nadal = A, serwis = a1, ale wymiary/waga = wartosci z presetu
    3. Potwierdz ze formularz sie auto-submituje
    4. Otworz /orders/{id} z istniejacymi paczkami — brak znaku "-" w kolumnie etykiet
  </verify>
  <done>AC-1, AC-4 satisfied</done>
</task>

<task type="auto">
  <name>Task 2: Endpoint GET /api/print/jobs/status + repo method</name>
  <files>src/Modules/Printing/PrintJobRepository.php, src/Modules/Printing/PrintApiController.php, routes/web.php</files>
  <action>
    PrintJobRepository.php — dodaj metode:
    ```
    /**
     * @param list<int> $packageIds
     * @return list<int>  package_ids ktore maja job status=pending
     */
    public function filterPendingPackageIds(array $packageIds): array
    ```
    Implementacja: jesli pusta tablica -> return []; przygotuj IN (...) placeholdery, SELECT DISTINCT package_id FROM print_jobs WHERE status='pending' AND package_id IN (...).

    PrintApiController.php — dodaj publiczna metode `status(Request $request): Response`:
    - Pobierz parametr `package_ids` (CSV lub query array), parsuj do list<int>, odfiltruj <=0, limit 100 wartosci.
    - Jesli pusty -> zwroc JSON {"pending":[]}.
    - Wywolaj PrintJobRepository::filterPendingPackageIds()
    - Zwroc JSON {"pending":[1,2,3]} (pakiety nadal w kolejce).
    - Auth: authMiddleware (ten sam co createJob) — tylko zalogowani uzytkownicy.

    routes/web.php — zarejestruj:
    ```
    $router->get('/api/print/jobs/status', [$printApiController, 'status'], [$authMiddleware]);
    ```
    przy pozostalych trasach /api/print/jobs.

    Avoid: dodawania kolumn do print_jobs, zmian w logice completed/failed, nie ruszaj apiKeyMiddleware tras (listPending/download/complete).
  </action>
  <verify>
    curl "http://localhost/api/print/jobs/status?package_ids=1,2,3" (z sesja) zwraca {"pending":[...]} JSON
  </verify>
  <done>Endpoint dostepny dla AC-3</done>
</task>

<task type="auto">
  <name>Task 3: Polling kolejki + auto-click ostatniej etykiety (JS)</name>
  <files>resources/views/orders/show.php, resources/views/shipments/prepare.php</files>
  <action>
    W orders/show.php (w istniejacym bloku script ~ linia 897-935):
    - Po kliknieciu btn-print-label i ustawieniu "W kolejce" wywolaj schedulePrintQueuePoll(packageId, btn).
    - Dodaj funkcje schedulePrintQueuePoll(ids, btnMap):
      - trzymaj mape packageId -> btn element
      - co 3 sekundy fetch GET /api/print/jobs/status?package_ids=<csv>
      - dla kazdego ID NIEobecnego w response.pending: zrevertuj przycisk do stanu Drukuj (innerHTML='Drukuj', disabled=false, remove btn--danger, add btn--secondary)
      - gdy mapa pusta — clearInterval
      - max 120 iteracji (6 minut) jako safety; po tym clear.
    - Przy wejsciu na strone (DOMContentLoaded) zbierz wszystkie istniejace `button[disabled]` z textem "W kolejce" i ich data-package-id pobrane z siostrzanego .btn-print-label lub z dodanego atrybutu data-package-id na samym disabled button. Zmodyfikuj szablon PHP aby disabled button "W kolejce" mial `data-package-id` i klase `js-print-queue-pending` — dla obu widokow.
    - Dla kazdego znalezionego `.js-print-queue-pending` uruchom schedulePrintQueuePoll.

    Auto-click ostatniej etykiety po utworzeniu przesylki (orders/show.php):
    - Read query param `?shipment_created=1` lub (prefered) flash session `shipment.created_package_id` ustawiana przez OrdersController/ShipmentsController po utworzeniu paczki.
    - Jezeli nie chcesz ruszac kontrolera — zastosuj fallback JS: po zaladowaniu strony jesli URL ma fragment `#tab=shipments` lub query `?printLast=1`, znajdz ostatni wiersz tabeli przesylek (tbody tr:last-child) ktory ma .btn-print-label i wywolaj btn.click().
    - WYBIERZ: dolozyc query param `printLast=1` w redirect z ShipmentsController po pomyslnym utworzeniu paczki (jesli istnieje taki redirect -> /orders/{id}#shipments). Znajdz redirect post utworzeniu paczki w ShipmentsController i dolaczaj ?printLast=1 do URL.
    - JS w show.php: jesli location.search zawiera `printLast=1`, poczekaj 300ms po inicjalizacji tabow, znajdz w tabeli przesylek OSTATNI .btn-print-label (nie disabled) i wywolaj .click(). Nastepnie wyczysc parametr z URL przez history.replaceState.

    Powtorz logike polling w shipments/prepare.php — dokladnie te same fragmenty (wspolna implementacja w widoku, bo oba pliki maja lokalne skrypty; DRY nie jest tu wymagany, ale jesli latwo to wydziel do resources/views/components/print-queue-poll.php i includuj).

    Avoid: dotykania logiki tworzenia przesylki (backend), zmian w API createJob, zmian w Windows clients.
  </action>
  <verify>
    1. /orders/{id} z jedna paczka label_ready — kliknij Drukuj, sprawdz ze pojawia sie "W kolejce"
    2. W DB: UPDATE print_jobs SET status='completed' WHERE package_id=X
    3. W ciagu <=10s przycisk wraca do "Drukuj"
    4. Stworz nowa przesylke z /shipments/prepare — po redirecie na /orders/{id}?printLast=1 automatycznie pojawia sie "W kolejce" dla nowej paczki
  </verify>
  <done>AC-2, AC-3 satisfied</done>
</task>

</tasks>

<boundaries>

## DO NOT CHANGE
- Logika tworzenia print_job po stronie backendu (createJob, PrintJobRepository::create)
- Windows client OrderPROPrint (poll interval / timeout)
- Preset CRUD w Settings (formularz, walidacja, zapis DB)
- Kolumna etykiety dla shipments "is_manual" (zostawia &mdash;)

## SCOPE LIMITS
- Polling tylko dla paczek widocznych na biezacej stronie (nie globalny)
- Endpoint /api/print/jobs/status tylko GET, read-only
- Nie zmieniamy schemy print_jobs ani dodawania nowych statusow

</boundaries>

<verification>
- [ ] php -l resources/views/shipments/prepare.php
- [ ] php -l resources/views/orders/show.php
- [ ] php -l src/Modules/Printing/PrintApiController.php
- [ ] php -l src/Modules/Printing/PrintJobRepository.php
- [ ] Rebuild CSS niepotrzebny (brak zmian SCSS)
- [ ] Manualny test AC-1..AC-4 zgodnie z verify w taskach
</verification>

<success_criteria>
- Wszystkie AC spelnione
- Brak nowych bledow PHP lint / konsoli JS
- Istniejace zachowania presetow (auto-submit) i tworzenia przesylek niezmienione
</success_criteria>

<output>
Po ukonczeniu stworz `.paul/phases/100-preset-scope-print-ux/100-01-SUMMARY.md`
</output>
