14 KiB
14 KiB
phase, plan, type, wave, depends_on, files_modified, autonomous, delegation
| phase | plan | type | wave | depends_on | files_modified | autonomous | delegation | |||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 94-order-preview-popup | 01 | execute | 1 |
|
true | off |
Purpose
Oszczednosc czasu — sprzedawca nie musi wchodzic na strone szczegolowy zamowienia, zeby skopiowac adres, numer zamowienia, dane kupujacego itp. Jeden klik otwiera podglad z ikonami kopiowania.
Output
- Endpoint AJAX:
GET /api/orders/{id}/previewzwracajacy HTML fragmentu podgladu - Partial:
resources/views/orders/partials/preview-modal.php— modal overlay - Przycisk oka w kolumnie
order_refkazdego wiersza na liscie - Ikony kopiowania przy kluczowych polach (adres dostawy, kupujacy, nr zamowienia)
Source Files
@src/Modules/Orders/OrdersController.php @src/Modules/Orders/OrdersRepository.php @resources/views/orders/list.php @resources/views/orders/show.php @resources/views/components/table-list.php @resources/views/orders/partials/email-send-modal.php @routes/web.php @resources/scss/app.scss @resources/lang/pl.php
<acceptance_criteria>
AC-1: Przycisk podgladu widoczny na liscie zamowien
Given lista zamowien /orders/list jest wyswietlona
When uzytkownik widzi wiersz zamowienia
Then w kolumnie numeru zamowienia (order_ref) widoczna jest ikona oka (podglad)
And ikona ma tooltip "Podglad"
AC-2: Klikniecie ikony otwiera popup z danymi zamowienia
Given lista zamowien jest wyswietlona
When uzytkownik klika ikone podgladu przy zamowieniu
Then otwiera sie modal overlay z danymi zamowienia zaladowanymi przez AJAX
And modal zawiera: dane kupujacego, adres dostawy, produkty, podsumowanie kwot, nr zamowienia
And podczas ladowania widoczny jest wskaznik ladowania (spinner/tekst)
AC-3: Kopiowanie danych do schowka
Given popup podgladu zamowienia jest otwarty
When uzytkownik klika ikone kopiowania przy polu (np. adres dostawy, imie kupujacego, nr zamowienia)
Then tresc pola jest kopiowana do schowka
And pojawia sie krotkie potwierdzenie (np. zmiana ikony na checkmark na 1.5s)
AC-4: Zamykanie popupu
Given popup podgladu jest otwarty
When uzytkownik klika przycisk X lub tlo (backdrop) lub naciska Escape
Then popup sie zamyka
AC-5: Link do pelnych szczegolow z popupu
Given popup podgladu jest otwarty
When uzytkownik klika "Pelne szczegoly" w stopce popupu
Then zostaje przekierowany na /orders/{id}
</acceptance_criteria>
Task 1: Endpoint AJAX preview + routing src/Modules/Orders/OrdersController.php, routes/web.php 1. W `OrdersController` dodac metode `preview(Request $request): Response`: - Pobierac `id` z request - Wywolac `$this->orders->findDetails($orderId)` (istniejaca metoda) - Jezeli null -> Response::json(['error' => 'Not found'], 404) - Przygotowac dane do widoku: order, items, addresses (customer/delivery/invoice), payments summary - Wyrenderowac partial `orders/partials/preview-content` (sam content, bez modala — modal jest w liscie) - Zwrocic Response::html($html) (fragment HTML, nie pelna strona)2. W `routes/web.php` dodac route:
```php
$router->get('/api/orders/{id}/preview', [$ordersController, 'preview'], [$authMiddleware]);
```
Dodac PO linii z `/api/orders/search`.
Metoda `preview()` renderuje partial BEZ layoutu (nie przekazywac layoutu do template->render).
Uzyc `$this->template->renderPartial('orders/partials/preview-content', $data)` lub render bez layoutu.
Sprawdzic jak dziala renderPartial w Template — jezeli nie istnieje, uzyc `render()` z trzecim parametrem null/pustym.
Avoid: NIE zwracac JSON — zwracamy gotowy HTML fragment do wstawienia w modal
GET /api/orders/{id}/preview zwraca HTML fragment z danymi zamowienia (nie pelna strone)
AC-2 (backend) satisfied — endpoint zwraca HTML podgladu
Task 2: Modal partial + przycisk w liscie + JS fetch + kopiowanie
resources/views/orders/partials/preview-modal.php,
resources/views/orders/list.php,
src/Modules/Orders/OrdersController.php
**preview-modal.php** — kontener modala (pusty, wypelniany AJAXem):
```php
**preview-content partial** (renderowane przez endpoint, wstawiane do #order-preview-body):
Nowy plik `resources/views/orders/partials/preview-content.php`:
- Sekcja: Kupujacy (imie, email, telefon) — z ikonami kopiowania (data-copy-value)
- Sekcja: Nr zamowienia (internal_order_number, external_order_id) — z ikonami kopiowania
- Sekcja: Adres dostawy (pelny adres sformatowany w jednej linii) — z ikona kopiowania calego adresu
- Sekcja: Produkty — lista (nazwa, qty, cena) — kompaktowa tabela
- Sekcja: Podsumowanie (total, oplacono, waluta, typ platnosci)
Kazde pole z kopiowaniem: `<span class="copy-field" data-copy-value="WARTOSC"><span class="copy-field__text">WARTOSC</span><button type="button" class="copy-field__btn" title="Kopiuj">📋</button></span>`
Zamiast emoji uzyc SVG inline lub znaku Unicode — np. ikona clipboard (ten sam pattern co Phase 92 buyer name copy).
**list.php** — dodac:
1. Na koncu pliku (przed zamykajacym tagiem) dolaczyc partial: `<?php require __DIR__ . '/partials/preview-modal.php'; ?>`
2. Dolaczyc skrypt JS (inline lub osobny plik) obslugi:
**JS w list.php** (inline `<script>`):
- Delegacja klikniecia: `document.addEventListener('click', ...)` na `.js-order-preview-btn`
- Po kliknieciu:
a) Pobrac `data-order-id` z przycisku
b) Otworzyc overlay (display:flex)
c) Ustawic body na "Ladowanie..."
d) fetch(`/api/orders/${id}/preview`) → wstawic HTML do `#order-preview-body`
e) Ustawic href `#order-preview-details-link` na `/orders/${id}`
- Zamykanie: klik X, klik backdrop (overlay), Escape
- Delegacja kopiowania: klik na `.copy-field__btn`:
a) Pobrac `data-copy-value` z rodzica `.copy-field`
b) `navigator.clipboard.writeText(value)`
c) Zmienic ikone na checkmark (✓) na 1.5s, potem przywrocic
**OrdersController::toTableRow()** — dodac ikone podgladu w kolumnie `order_ref`:
Dodac przycisk z ikona oka PRZED linkiem zamowienia:
```php
'<button type="button" class="btn-icon js-order-preview-btn" data-order-id="' . (int) ($row['id'] ?? 0) . '" title="Podglad">👁</button>'
```
Uzyc ikony SVG inline lub unicode eye (👁) — preferowac prosty SVG jak w istniejacych ikonach projektu.
Dodac ten przycisk w `order_ref` HTML, np. na poczatku diva `orders-ref`.
Avoid:
- NIE uzywac natywnych alert()/confirm()
- NIE ladowac pelnej strony w modalu (tylko fragment)
- NIE dodawac nowych zaleznosci JS
1. Na liscie zamowien widoczna ikona oka przy kazdym zamowieniu
2. Klikniecie ikony otwiera modal z danymi zamowienia (AJAX)
3. Ikona kopiowania kopiuje dane do schowka
4. X / backdrop / Escape zamyka modal
5. "Pelne szczegoly" prowadzi do /orders/{id}
AC-1, AC-2, AC-3, AC-4, AC-5 satisfied
Task 3: Style SCSS + tlumaczenia
resources/scss/components/_order-preview-modal.scss,
resources/scss/app.scss,
resources/lang/pl.php
**_order-preview-modal.scss** — nowy plik SCSS:
```scss
.order-preview-overlay {
position: fixed;
inset: 0;
z-index: 1000;
background: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
}
.order-preview-modal {
background: var(--c-surface);
border: 1px solid var(--c-border);
border-radius: 10px;
box-shadow: 0 16px 48px rgba(0,0,0,0.18);
width: 100%;
max-width: 640px;
max-height: 85vh;
display: flex;
flex-direction: column;
&__header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 16px 20px;
border-bottom: 1px solid var(--c-border);
}
&__title {
font-size: 16px;
font-weight: 600;
margin: 0;
}
&__close {
background: none;
border: none;
font-size: 22px;
cursor: pointer;
color: var(--c-muted);
padding: 0 4px;
line-height: 1;
&:hover { color: var(--c-text); }
}
&__body {
padding: 16px 20px;
overflow-y: auto;
flex: 1;
}
&__footer {
display: flex;
align-items: center;
justify-content: flex-end;
gap: 8px;
padding: 12px 20px;
border-top: 1px solid var(--c-border);
}
}
.order-preview-loading {
text-align: center;
padding: 32px;
color: var(--c-muted);
}
.order-preview-section {
margin-bottom: 14px;
&__title {
font-size: 12px;
font-weight: 600;
text-transform: uppercase;
color: var(--c-muted);
margin-bottom: 6px;
letter-spacing: 0.04em;
}
}
.order-preview-kv {
display: grid;
grid-template-columns: auto 1fr;
gap: 2px 12px;
font-size: 13px;
dt { color: var(--c-muted); white-space: nowrap; }
dd { margin: 0; }
}
.order-preview-items {
width: 100%;
font-size: 13px;
border-collapse: collapse;
th, td { padding: 4px 8px; text-align: left; }
th { font-weight: 600; font-size: 11px; text-transform: uppercase; color: var(--c-muted); }
tbody tr + tr { border-top: 1px solid var(--c-border); }
}
.copy-field {
display: inline-flex;
align-items: center;
gap: 4px;
&__btn {
background: none;
border: none;
cursor: pointer;
font-size: 13px;
color: var(--c-muted);
padding: 0 2px;
line-height: 1;
opacity: 0.6;
transition: opacity 0.15s;
&:hover { opacity: 1; color: var(--c-primary, #4f6ef7); }
&.is-copied { color: #22c55e; opacity: 1; }
}
}
.btn-icon.js-order-preview-btn {
background: none;
border: none;
cursor: pointer;
font-size: 14px;
color: var(--c-muted);
padding: 2px 4px;
line-height: 1;
opacity: 0.6;
transition: opacity 0.15s;
vertical-align: middle;
&:hover { opacity: 1; color: var(--c-primary, #4f6ef7); }
}
```
**app.scss** — dodac import:
Znalezc istniejace importy komponentow i dodac: `@use "components/order-preview-modal";`
**pl.php** — dodac klucze tlumaczen w sekcji `orders`:
```php
'preview' => [
'title' => 'Podglad zamowienia',
'buyer' => 'Kupujacy',
'order_number' => 'Nr zamowienia',
'delivery_address' => 'Adres dostawy',
'products' => 'Produkty',
'summary' => 'Podsumowanie',
'full_details' => 'Pelne szczegoly',
'close' => 'Zamknij',
'loading' => 'Ladowanie...',
'copy_tooltip' => 'Kopiuj',
],
```
Po zmianach: `npm run build:css`
Avoid: NIE trzymac styli w pliku widoku — SCSS w osobnym pliku
1. SCSS buduje sie bez bledow
2. Modal ma poprawne style — centrowany, zaokraglony, z cieniem
3. Ikony kopiowania sa widoczne i reaguja na hover
4. Tlumaczenia dostepne w pl.php
AC-1 (style), AC-2 (style), AC-3 (style) satisfied
DO NOT CHANGE
- resources/views/components/table-list.php (komponent reuzywany — nie modyfikowac)
- src/Modules/Orders/OrdersRepository.php (findDetails juz istnieje — uzyc bez zmian)
- resources/views/orders/show.php (strona szczegolow — bez zmian)
- resources/views/orders/partials/email-send-modal.php (istniejacy modal — bez zmian)
SCOPE LIMITS
- Nie dodajemy edycji z popupu — tylko podglad i kopiowanie
- Nie dodajemy nowych zaleznosci npm/composer
- Nie modyfikujemy OrdersRepository — uzywamy istniejacego findDetails()
- Popup nie obsluguje akcji (zmiana statusu, platnosc itp.)
<success_criteria>
- All tasks completed
- All verification checks pass
- No errors or warnings introduced
- Uzytkownik moze szybko podejrzec i skopiowac dane zamowienia z listy </success_criteria>