--- 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 After completion, create `.paul/phases/95-ajax-table-refresh/95-01-SUMMARY.md`