---
phase: 19-ui-integration
plan: 01
subsystem: ui
tags: [printing, ajax, bulk-actions, label-queue]

requires:
  - phase: 18-print-queue-backend
    provides: PrintApiController, PrintJobRepository, print_jobs table, API key auth
provides:
  - Przycisk "Drukuj" w widoku przesyłki i szczegółów zamówienia
  - Bulk print z listy zamówień
  - Kolejka wydruku w Ustawienia > Drukowanie
  - Endpoint POST /api/print/jobs/bulk
affects: [20-windows-client]

tech-stack:
  added: []
  patterns: [ShipmentProviderRegistry for ensureLabel(), pendingPackageIds for duplicate protection]

key-files:
  created:
    - src/Modules/Printing/PrintApiController.php (bulkCreateJobs, ensureLabel)
    - src/Modules/Printing/PrintJobRepository.php (findPendingByPackageId, pendingPackageIds)
    - src/Modules/Settings/PrintSettingsController.php (kolejka wydruku)
    - resources/views/settings/printing.php (kolejka UI)
    - resources/scss/modules/_printing.scss
    - database/migrations/20260322_000058_create_print_tables.sql
  modified:
    - resources/views/shipments/prepare.php (przycisk Drukuj, label file check)
    - resources/views/orders/show.php (przycisk Drukuj, tab persistence, carrier_id column)
    - resources/views/orders/list.php (bulk print action)
    - routes/web.php (DI + nowe route'y)
    - src/Modules/Orders/OrdersController.php (storagePath + printJobRepo injection)
    - src/Modules/Shipments/ShipmentController.php (redirect po utworzeniu przesyłki)
    - src/Modules/Shipments/ApaczkaShipmentService.php (carrier_id = service name)
    - src/Modules/Settings/ApaczkaApiClient.php (fix use statement)
    - resources/scss/app.scss (_printing import)
    - public/assets/css/app.css (compiled)

key-decisions:
  - "ensureLabel() auto-downloads label via ShipmentProviderRegistry before creating print job"
  - "findPendingByPackageId protects against duplicate pending jobs"
  - "Apaczka carrier_id stores service name (e.g. 'Orlen Paczka') for display"
  - "Tab persistence via localStorage in show.php"
  - "Label file existence check hides Pobierz/Drukuj when file missing on disk"

patterns-established:
  - "ShipmentProviderRegistry pattern for multi-provider label operations"
  - "Bulk endpoint returns {created: [], skipped: []} JSON structure"

duration: ~4h
started: 2026-03-22T10:00:00Z
completed: 2026-03-22T22:00:00Z
---

# Phase 19 Plan 01: UI Integration Summary

**Przycisk "Drukuj" w widoku przesyłki, bulk print z listy zamówień, kolejka wydruku w ustawieniach — pełna integracja UI z backendem kolejki wydruku z fazy 18.**

## Performance

| Metric | Value |
|--------|-------|
| Duration | ~4h (rozłożone na 2 sesje) |
| Started | 2026-03-22 |
| Completed | 2026-03-22 |
| Tasks | 3 (2 auto + 1 checkpoint) |
| Files modified | 14 |

## Acceptance Criteria Results

| Criterion | Status | Notes |
|-----------|--------|-------|
| AC-1: Przycisk "Drukuj" w widoku przesyłki | Pass | Widoczny w prepare.php i show.php, AJAX feedback + duplikat protection |
| AC-2: Zbiorcze drukowanie z listy zamówień | Pass | Checkboxy + header action "Drukuj etykiety", bulk endpoint |
| AC-3: Kolejka wydruku w ustawieniach | Pass | Tabela zleceń z filtrami statusu, retry dla failed |
| AC-4: Endpoint bulk create | Pass | POST /api/print/jobs/bulk z {package_ids/order_ids} |

## Accomplishments

- Przycisk "Drukuj" obok "Pobierz" z AJAX feedback i ochroną przed duplikatami
- Bulk print z listy zamówień (checkboxy + nagłówkowa akcja)
- Kolejka wydruku w Ustawienia > Drukowanie z filtrami i retry
- Auto-download etykiety (ensureLabel) przez ShipmentProviderRegistry
- Stan "W kolejce" (disabled, czerwony) gdy pending job istnieje

## Deviations from Plan

### Summary

| Type | Count | Impact |
|------|-------|--------|
| Scope additions | 6 | Usprawnienia UX wykryte podczas testów |
| Auto-fixed | 1 | Bug fix ApaczkaApiClient |
| Deferred | 0 | — |

**Total impact:** Dodatkowe usprawnienia UX poza planem, zero regresji.

### Scope Additions (poza planem)

1. **show.php tab persistence** — localStorage zapamiętuje aktywny tab
2. **show.php label file check** — ukrywa Pobierz/Drukuj gdy plik nie istnieje na dysku
3. **show.php przycisk Drukuj** — plan dotyczył tylko prepare.php, dodano też w show.php
4. **Kolumna Przewoznik** — "Apaczka → Orlen Paczka" zamiast pustego carrier_id
5. **Redirect po utworzeniu przesyłki** — ShipmentController redirect → /orders/{id} z flash
6. **Sekcja przesyłek przeniesiona** — pod formularz nowej przesyłki w prepare.php

### Auto-fixed Issues

**1. ApaczkaApiClient use statement bug**
- **Found during:** Task 1
- **Issue:** Brak backslashy w use statement
- **Fix:** Poprawiony import namespace
- **Files:** src/Modules/Settings/ApaczkaApiClient.php

## SonarQube Scan

**Scan date:** 2026-03-22
**Result:** 0 new blocker/critical issues on phase 19 files
**New issues (minor/major):**
- show.php:696 — S4833 require → use, S2003 require → require_once
- OrdersController — S1448 (22 methods > 20), S1142 (bulkPrint 5 returns)

All logged to DOCS/todo.md.

## Next Phase Readiness

**Ready:**
- Pełne UI do zarządzania kolejką wydruku
- API endpoints gotowe dla Windows Client (faza 20)
- print_jobs table z pełnym lifecycle (pending → completed/failed)

**Concerns:**
- OrdersController rośnie (22 metody) — rozważyć wydzielenie PrintController w przyszłości

**Blockers:**
- None

---
*Phase: 19-ui-integration, Plan: 01*
*Completed: 2026-03-22*
