192 lines
7.6 KiB
Markdown
192 lines
7.6 KiB
Markdown
---
|
|
phase: 95-ajax-table-refresh
|
|
plan: 01
|
|
type: execute
|
|
wave: 1
|
|
depends_on: []
|
|
files_modified:
|
|
- src/Modules/Orders/OrdersController.php
|
|
- public/assets/js/modules/inline-status-change.js
|
|
- resources/views/orders/list.php
|
|
- resources/views/components/table-list.php
|
|
- resources/views/components/order-status-panel.php
|
|
autonomous: false
|
|
delegation: off
|
|
---
|
|
|
|
<objective>
|
|
## Goal
|
|
Zamiana `location.reload()` po zmianie statusu zamówienia na AJAX refresh samej tabeli, paginacji i panelu statusów — bez przeładowania całej strony.
|
|
|
|
## Purpose
|
|
Zmiana statusu inline powoduje pełny reload strony, co jest wolne i resetuje scroll, filtry wizualne, itp. AJAX refresh da szybszą, płynniejszą obsługę.
|
|
|
|
## Output
|
|
- Kontroler `index()` rozpoznaje AJAX request i zwraca JSON z HTML fragmentami (tabela + panel statusów)
|
|
- JS po zmianie statusu fetchuje aktualną tabelę i panel, podmienia DOM bez reload
|
|
</objective>
|
|
|
|
<context>
|
|
## Project Context
|
|
@.paul/PROJECT.md
|
|
@.paul/ROADMAP.md
|
|
@.paul/STATE.md
|
|
|
|
## Source Files
|
|
@src/Modules/Orders/OrdersController.php (metoda index() linie 44-157, metoda updateStatus() linia 250)
|
|
@public/assets/js/modules/inline-status-change.js (location.reload() linia 155)
|
|
@resources/views/orders/list.php (struktura strony, require table-list.php linia 22)
|
|
@resources/views/components/table-list.php (tabela + paginacja)
|
|
@resources/views/components/order-status-panel.php (panel statusów z licznikami)
|
|
@src/Core/View/Template.php (render() z null layout zwraca sam HTML)
|
|
</context>
|
|
|
|
<skills>
|
|
No specialized flows configured.
|
|
</skills>
|
|
|
|
<acceptance_criteria>
|
|
|
|
## AC-1: AJAX refresh tabeli po zmianie statusu
|
|
```gherkin
|
|
Given użytkownik jest na /orders/list z filtrami/paginacją
|
|
When zmieni status zamówienia przez inline dropdown
|
|
Then tabela i paginacja odświeżą się bez przeładowania strony
|
|
And filtry, strona i sortowanie pozostaną zachowane
|
|
And scroll pozycja strony nie zmieni się
|
|
```
|
|
|
|
## AC-2: AJAX refresh panelu statusów
|
|
```gherkin
|
|
Given użytkownik zmienił status zamówienia
|
|
When tabela się odświeży
|
|
Then panel statusów (liczniki) też się odświeży z aktualnymi wartościami
|
|
```
|
|
|
|
## AC-3: Obsługa błędu AJAX refresh
|
|
```gherkin
|
|
Given zmiana statusu się powiodła ale fetch tabeli zawiódł
|
|
When sieć jest niedostępna lub serwer zwraca błąd
|
|
Then badge statusu pozostaje zaktualizowany (optimistic update)
|
|
And strona nie crashuje — użytkownik może kontynuować pracę
|
|
```
|
|
|
|
</acceptance_criteria>
|
|
|
|
<tasks>
|
|
|
|
<task type="auto">
|
|
<name>Task 1: Endpoint AJAX dla fragmentów tabeli i panelu</name>
|
|
<files>src/Modules/Orders/OrdersController.php</files>
|
|
<action>
|
|
W metodzie `index()` dodać detekcję AJAX requestu (header `X-Requested-With: XMLHttpRequest`).
|
|
|
|
Gdy request jest AJAX:
|
|
1. Zbudować te same dane co normalnie (filtry, paginacja, tableRows, statusPanel)
|
|
2. Renderować dwa fragmenty osobno przez `$this->template->render()` BEZ layoutu (null):
|
|
- `components/table-list` z danymi `$tableList` (tabela + paginacja)
|
|
- `components/order-status-panel` z danymi `$statusPanelList` i `$statusPanelTitle`
|
|
3. Zwrócić JSON: `{"tableHtml": "...", "panelHtml": "..."}`
|
|
|
|
Zmienne potrzebne do renderowania partiali muszą być przekazane w `$data`:
|
|
- Dla table-list: klucz `tableList` (już jest budowany)
|
|
- Dla order-status-panel: klucze `statusPanelList`, `statusPanelTitle`, `query` (filtry)
|
|
|
|
Ważne:
|
|
- Użyć `Response::json()` dla AJAX odpowiedzi
|
|
- Helpery `$e`, `$t` i inne muszą być dostępne w renderowanych partialach (Template::render je dodaje)
|
|
- Nie zmieniać normalnego (nie-AJAX) flow — ma działać jak dotychczas
|
|
</action>
|
|
<verify>
|
|
curl -H "X-Requested-With: XMLHttpRequest" "http://localhost/orders/list?page=1"
|
|
powinien zwrócić JSON z kluczami tableHtml i panelHtml
|
|
</verify>
|
|
<done>AC-1 i AC-2 częściowo — backend zwraca fragmenty HTML przez AJAX</done>
|
|
</task>
|
|
|
|
<task type="auto">
|
|
<name>Task 2: JS — AJAX refresh zamiast location.reload()</name>
|
|
<files>public/assets/js/modules/inline-status-change.js</files>
|
|
<action>
|
|
W funkcji `changeStatus()` zamienić `location.reload()` (linia 155) na:
|
|
|
|
1. Po udanej zmianie statusu (result.ok && result.data.success):
|
|
- Badge już jest zaktualizowany (optimistic update — zostaje)
|
|
- Pobrać aktualny URL strony: `window.location.pathname + window.location.search`
|
|
- Fetch GET na ten URL z headerem `X-Requested-With: XMLHttpRequest`
|
|
- Z odpowiedzi JSON wyciągnąć `tableHtml` i `panelHtml`
|
|
|
|
2. Podmiana DOM:
|
|
- Znaleźć kontener tabeli: `document.querySelector('.table-list')` (lub odpowiedni selektor dla table-list.php)
|
|
- Znaleźć kontener panelu statusów: `document.querySelector('.order-status-panel')`
|
|
- Zamienić innerHTML obu kontenerów na nowe HTML
|
|
|
|
3. Obsługa błędu:
|
|
- Jeśli fetch tabeli się nie powiedzie — nie robić nic (badge już zaktualizowany, dane nieco nieaktualne ale nie krytyczne)
|
|
- Nie wyświetlać błędu użytkownikowi — zmiana statusu się powiodła
|
|
|
|
Ważne:
|
|
- NIE usuwać optimistic update badge'a (linie 121-125) — to zostaje
|
|
- Scroll pozycja się nie zmieni bo nie robimy reload
|
|
- Po podmianie innerHTML, eventy inline-status-change nadal będą działać bo używają delegacji na document
|
|
</action>
|
|
<verify>
|
|
Na /orders/list zmienić status zamówienia — tabela i panel statusów odświeżą się bez reload strony, scroll się nie zmieni
|
|
</verify>
|
|
<done>AC-1, AC-2, AC-3 — pełny AJAX refresh bez reload</done>
|
|
</task>
|
|
|
|
<task type="checkpoint:human-verify" gate="blocking">
|
|
<what-built>AJAX refresh tabeli i panelu statusów po zmianie statusu zamówienia</what-built>
|
|
<how-to-verify>
|
|
1. Otwórz /orders/list
|
|
2. Przewiń stronę w dół
|
|
3. Zmień status dowolnego zamówienia przez kliknięcie w badge
|
|
4. Potwierdź:
|
|
- Tabela odświeżyła się (nowy status widoczny)
|
|
- Panel statusów (liczniki) zaktualizował się
|
|
- Strona NIE przeładowała się (scroll pozycja zachowana)
|
|
- Filtry i paginacja zachowane
|
|
5. Zmień stronę paginacji, powtórz zmianę statusu — to samo zachowanie
|
|
6. Zastosuj filtr (np. po źródle), zmień status — filtr zachowany po refresh
|
|
</how-to-verify>
|
|
<resume-signal>Type "approved" to continue, or describe issues to fix</resume-signal>
|
|
</task>
|
|
|
|
</tasks>
|
|
|
|
<boundaries>
|
|
|
|
## DO NOT CHANGE
|
|
- resources/views/components/table-list.php (struktura HTML — tylko czytać, nie modyfikować)
|
|
- resources/views/components/order-status-panel.php (struktura HTML — tylko czytać)
|
|
- src/Core/View/Template.php (engine renderowania)
|
|
- routes/web.php (nie potrzeba nowej trasy — istniejąca GET /orders/list wystarczy)
|
|
|
|
## SCOPE LIMITS
|
|
- Tylko zmiana statusu inline — nie dotyczy innych akcji na liście
|
|
- Nie dodawać animacji/transition przy refresh (prostota)
|
|
- Nie zmieniać struktury HTML table-list ani order-status-panel
|
|
|
|
</boundaries>
|
|
|
|
<verification>
|
|
Before declaring plan complete:
|
|
- [ ] Zmiana statusu inline odświeża tabelę przez AJAX (bez reload)
|
|
- [ ] Panel statusów odświeża się razem z tabelą
|
|
- [ ] Scroll pozycja zachowana
|
|
- [ ] Filtry i paginacja zachowane po refresh
|
|
- [ ] Normalny (nie-AJAX) request na /orders/list nadal zwraca pełną stronę
|
|
- [ ] Brak błędów JS w konsoli
|
|
</verification>
|
|
|
|
<success_criteria>
|
|
- location.reload() usunięty z inline-status-change.js
|
|
- Kontroler index() zwraca JSON z fragmentami HTML dla AJAX requestów
|
|
- Tabela, paginacja i panel statusów odświeżają się bez przeładowania strony
|
|
</success_criteria>
|
|
|
|
<output>
|
|
After completion, create `.paul/phases/95-ajax-table-refresh/95-01-SUMMARY.md`
|
|
</output>
|