---
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
---
## 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
## 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)
No specialized flows configured.
## 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ę
```
Task 1: Endpoint AJAX dla fragmentów tabeli i panelu
src/Modules/Orders/OrdersController.php
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
curl -H "X-Requested-With: XMLHttpRequest" "http://localhost/orders/list?page=1"
powinien zwrócić JSON z kluczami tableHtml i panelHtml
AC-1 i AC-2 częściowo — backend zwraca fragmenty HTML przez AJAX
Task 2: JS — AJAX refresh zamiast location.reload()
public/assets/js/modules/inline-status-change.js
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
Na /orders/list zmienić status zamówienia — tabela i panel statusów odświeżą się bez reload strony, scroll się nie zmieni
AC-1, AC-2, AC-3 — pełny AJAX refresh bez reload
AJAX refresh tabeli i panelu statusów po zmianie statusu zamówienia
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
Type "approved" to continue, or describe issues to fix
## 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
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
- 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