update
This commit is contained in:
191
.paul/phases/95-ajax-table-refresh/95-01-PLAN.md
Normal file
191
.paul/phases/95-ajax-table-refresh/95-01-PLAN.md
Normal file
@@ -0,0 +1,191 @@
|
||||
---
|
||||
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>
|
||||
83
.paul/phases/95-ajax-table-refresh/95-01-SUMMARY.md
Normal file
83
.paul/phases/95-ajax-table-refresh/95-01-SUMMARY.md
Normal file
@@ -0,0 +1,83 @@
|
||||
---
|
||||
phase: 95-ajax-table-refresh
|
||||
plan: 01
|
||||
subsystem: ui
|
||||
tags: [ajax, dom-replacement, inline-status, orders-list]
|
||||
|
||||
requires:
|
||||
- phase: 80-status-change-reload
|
||||
provides: inline status change with location.reload()
|
||||
provides:
|
||||
- AJAX table refresh without full page reload
|
||||
- JSON endpoint for partial HTML fragments
|
||||
affects: []
|
||||
|
||||
tech-stack:
|
||||
added: []
|
||||
patterns: [ajax-partial-render, json-html-fragments]
|
||||
|
||||
key-files:
|
||||
modified:
|
||||
- src/Modules/Orders/OrdersController.php
|
||||
- public/assets/js/modules/inline-status-change.js
|
||||
|
||||
key-decisions:
|
||||
- "outerHTML replacement instead of innerHTML for table container"
|
||||
- "Silent failure on refresh fetch error — status already updated optimistically"
|
||||
|
||||
patterns-established:
|
||||
- "X-Requested-With detection for AJAX partial rendering in controllers"
|
||||
|
||||
duration: ~15min
|
||||
completed: 2026-04-10
|
||||
---
|
||||
|
||||
# Phase 95 Plan 01: AJAX Table Refresh Summary
|
||||
|
||||
**Zamiana location.reload() na AJAX refresh tabeli i panelu statusow po zmianie statusu inline — bez przeladowania strony.**
|
||||
|
||||
## Acceptance Criteria Results
|
||||
|
||||
| Criterion | Status | Notes |
|
||||
|-----------|--------|-------|
|
||||
| AC-1: AJAX refresh tabeli po zmianie statusu | Pass | Tabela i paginacja odswiezaja sie bez reload, scroll zachowany |
|
||||
| AC-2: AJAX refresh panelu statusow | Pass | Panel licznikow aktualizuje sie razem z tabela |
|
||||
| AC-3: Obsluga bledu AJAX refresh | Pass | Badge zaktualizowany optimistic, brak crash przy bledzie fetch |
|
||||
|
||||
## Accomplishments
|
||||
|
||||
- Controller `index()` wykrywa AJAX request i zwraca JSON z `tableHtml` + `panelHtml`
|
||||
- JS `inline-status-change.js` po udanej zmianie statusu pobiera fragmenty i podmienia DOM
|
||||
- Scroll, filtry, paginacja zachowane po refresh
|
||||
|
||||
## Files Created/Modified
|
||||
|
||||
| File | Change | Purpose |
|
||||
|------|--------|---------|
|
||||
| `src/Modules/Orders/OrdersController.php` | Modified | AJAX detection + JSON response z partial HTML |
|
||||
| `public/assets/js/modules/inline-status-change.js` | Modified | Fetch + DOM replacement zamiast location.reload() |
|
||||
|
||||
## Decisions Made
|
||||
|
||||
| Decision | Rationale | Impact |
|
||||
|----------|-----------|--------|
|
||||
| outerHTML zamiast innerHTML | Prostsza podmiana calego kontenera bez wrapper div | Eventy delegowane na document nadal dzialaja |
|
||||
| Silent fail na fetch error | Zmiana statusu juz sie powiodla, refresh jest nice-to-have | UX nie przerywa pracy uzytkownika |
|
||||
|
||||
## Deviations from Plan
|
||||
|
||||
None — plan executed as written.
|
||||
|
||||
## Next Phase Readiness
|
||||
|
||||
**Ready:**
|
||||
- Pattern AJAX partial render gotowy do reuse w innych miejscach
|
||||
- Inline status change w pelni asynchroniczny
|
||||
|
||||
**Concerns:** None
|
||||
|
||||
**Blockers:** None
|
||||
|
||||
---
|
||||
*Phase: 95-ajax-table-refresh, Plan: 01*
|
||||
*Completed: 2026-04-10*
|
||||
Reference in New Issue
Block a user