feat(05-admin-panel): Admin panel z historią rezerwacji

Phase 5 complete — CPT carei_reservation z automatycznym zapisem,
lista z kolumnami i filtrem statusu, meta box szczegółów,
system statusów nowe/przeczytane/zrealizowane, auto-mark-read.

Milestone v0.1 Formularz Rezerwacji MVP — all 5 phases complete.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-25 17:39:09 +01:00
parent a82ec90a51
commit 2af73782f2
11 changed files with 1261 additions and 23 deletions

View File

@@ -0,0 +1,274 @@
---
phase: 05-admin-panel
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
- wp-content/plugins/carei-reservation/includes/class-admin-panel.php
- wp-content/plugins/carei-reservation/includes/class-rest-proxy.php
- wp-content/plugins/carei-reservation/carei-reservation.php
autonomous: false
---
<objective>
## Goal
Admin panel w wp-admin do przeglądania rezerwacji: Custom Post Type `carei_reservation`, automatyczny zapis przy udanej rezerwacji, lista z kolumnami i filtrami, podgląd szczegółów, statusy (nowe/przeczytane/zrealizowane).
## Purpose
Właściciel firmy musi mieć przegląd wszystkich rezerwacji złożonych przez formularz — bez logowania do panelu Softra. Dane zapisane w WordPress = szybki podgląd, filtrowanie, zmiana statusu.
## Output
- Nowy plik: `includes/class-admin-panel.php` (CPT, kolumny, meta box, statusy)
- Zmodyfikowany: `includes/class-rest-proxy.php` (zapis rezerwacji po sukcesie)
- Zmodyfikowany: `carei-reservation.php` (include nowej klasy)
</objective>
<context>
## Project Context
@.paul/PROJECT.md
@.paul/ROADMAP.md
@.paul/STATE.md
## Prior Work
@.paul/phases/03-form-submit-booking/03-01-SUMMARY.md
- Booking flow: customer/add → pricingSummary → makebooking → confirm
- Dane zbierane: segment, daty, oddział, extras, imię, nazwisko, adres, email, telefon, PESEL, wiadomość
- Po sukcesie: reservationId + reservationNo z API
## Source Files
@wp-content/plugins/carei-reservation/carei-reservation.php
@wp-content/plugins/carei-reservation/includes/class-rest-proxy.php
</context>
<acceptance_criteria>
## AC-1: CPT carei_reservation zarejestrowany
```gherkin
Given plugin jest aktywny
When otworzę wp-admin
Then w menu bocznym widzę "Rezerwacje" z ikoną dashicons-car
And CPT nie jest publiczny (brak na frontendzie)
And supports: title (auto-generowany, nie edytowalny)
```
## AC-2: Rezerwacja zapisuje się automatycznie po sukcesie
```gherkin
Given użytkownik wypełnił formularz i potwierdził rezerwację
When API makebooking + confirm zwraca sukces
Then w wp-admin pojawia się nowy wpis z danymi rezerwacji
And tytuł: "Rezerwacja #[reservationNo] [Imię Nazwisko]"
And wszystkie dane formularza zapisane w post_meta
And status: "nowe"
```
## AC-3: Lista rezerwacji z kolumnami
```gherkin
Given jestem w wp-admin Rezerwacje
When widzę listę wpisów
Then kolumny: Nr rezerwacji | Klient | Segment | Daty | Oddział | Status | Data
And kolumna Status pokazuje kolorowy badge (nowe=niebieski, przeczytane=żółty, zrealizowane=zielony)
And mogę sortować po dacie
And mogę filtrować po statusie (dropdown nad listą)
```
## AC-4: Podgląd szczegółów rezerwacji
```gherkin
Given kliknę na rezerwację w liście
When otwiera się edycja wpisu
Then widzę meta box "Szczegóły rezerwacji" z tabelą:
- Nr rezerwacji, ID klienta Softra
- Segment, daty od-do, oddział odbioru, oddział zwrotu
- Imię, nazwisko, email, telefon, PESEL, adres
- Wybrane opcje dodatkowe
- Wiadomość klienta
And widzę dropdown do zmiany statusu (nowe przeczytane zrealizowane)
And status zmienia się po kliknięciu "Zaktualizuj"
```
## AC-5: Przy otwarciu rezerwacji status zmienia się na "przeczytane"
```gherkin
Given rezerwacja ma status "nowe"
When otwieram ją w wp-admin
Then status automatycznie zmienia się na "przeczytane"
And badge w liście aktualizuje się
```
</acceptance_criteria>
<tasks>
<task type="auto">
<name>Task 1: CPT registration + admin panel class</name>
<files>wp-content/plugins/carei-reservation/includes/class-admin-panel.php, wp-content/plugins/carei-reservation/carei-reservation.php</files>
<action>
1. **Utwórz `includes/class-admin-panel.php`:**
Klasa `Carei_Admin_Panel` z metodami:
a) `register_post_type()` — hook na `init`:
- CPT: `carei_reservation`
- label: "Rezerwacje" / "Rezerwacja"
- menu_icon: `dashicons-car`
- public: false, show_ui: true, show_in_menu: true
- supports: `['title']` (title auto-generowany)
- capability_type: 'post'
- menu_position: 26 (pod Komentarze)
b) `register_statuses()` — custom taxonomy NIE jest potrzebna, użyj post_meta `_carei_status` z wartościami: `nowe`, `przeczytane`, `zrealizowane`
c) `add_admin_columns($columns)` — hook `manage_carei_reservation_posts_columns`:
- Kolumny: cb, reservation_no, client, segment, dates, branch, status, date
- Usuń domyślny title
d) `render_admin_column($column, $post_id)` — hook `manage_carei_reservation_posts_custom_column`:
- reservation_no: get_post_meta `_carei_reservation_no`
- client: `_carei_first_name` + `_carei_last_name`
- segment: `_carei_segment`
- dates: `_carei_date_from` + `_carei_date_to` (format: d.m.Y H:i)
- branch: `_carei_pickup_branch`
- status: badge z kolorem (nowe=#2F2482, przeczytane=#f59e0b, zrealizowane=#22c55e)
e) `add_status_filter()` — hook `restrict_manage_posts`:
- Dropdown filtra statusu nad listą
- Opcje: Wszystkie, Nowe, Przeczytane, Zrealizowane
f) `filter_by_status($query)` — hook `pre_get_posts`:
- Filtruj po `_carei_status` meta_query
g) `add_meta_box()` — hook `add_meta_boxes`:
- Meta box "Szczegóły rezerwacji" w edycji wpisu
- Tabela z wszystkimi danymi
- Dropdown statusu z save
h) `save_meta_box($post_id)` — hook `save_post_carei_reservation`:
- Zapisz wybrany status
i) `auto_mark_read($post_id)` — hook `edit_form_after_title` lub `admin_head`:
- Jeśli status == 'nowe' i jesteśmy na ekranie edycji → zmień na 'przeczytane'
j) **Inline CSS** dla badge'ów statusu i meta box — dodaj przez `admin_head` hook, scoped do CPT screen
2. **Zmodyfikuj `carei-reservation.php`:**
- Dodaj `require_once` dla nowej klasy
- Zainicjalizuj `new Carei_Admin_Panel()` w `plugins_loaded`
Avoid: Nie twórz oddzielnych template files. Wszystko w jednej klasie. Nie dodawaj custom taxonomy — meta jest wystarczające.
</action>
<verify>
- Otwórz wp-admin → "Rezerwacje" widoczne w menu
- Lista pusta, kolumny widoczne
- Filtr statusu nad listą
</verify>
<done>AC-1, AC-3, AC-4, AC-5 satisfied: CPT zarejestrowany, kolumny, meta box, auto-read</done>
</task>
<task type="auto">
<name>Task 2: Zapis rezerwacji po sukcesie booking</name>
<files>wp-content/plugins/carei-reservation/includes/class-rest-proxy.php</files>
<action>
1. **W `class-rest-proxy.php`**, w callback dla `/booking` endpoint:
- Po udanym `make_booking()` i `confirm_booking()` (jeśli confirm jest w tym samym request) LUB:
- Lepiej: dodaj nowy statyczny helper `Carei_Admin_Panel::save_reservation($data, $result)`
2. **W callback `/booking`:**
- Po `$result = $api->make_booking($body)` z sukcesem:
- Wywołaj `Carei_Admin_Panel::save_reservation($body, $result)`
3. **Metoda `save_reservation($booking_data, $api_result)`:**
- `wp_insert_post()` z:
- post_type: `carei_reservation`
- post_title: `Rezerwacja #{reservationNo} — {firstName} {lastName}`
- post_status: `publish`
- `update_post_meta()` dla:
- `_carei_reservation_no` ← reservationNo
- `_carei_reservation_id` ← reservationId
- `_carei_customer_id` ← customerId
- `_carei_segment` ← carParameters.categoryName
- `_carei_date_from` ← dateFrom
- `_carei_date_to` ← dateTo
- `_carei_pickup_branch` ← pickUpLocation.branchName
- `_carei_return_branch` ← returnLocation.branchName
- `_carei_first_name` ← drivers[0].firstName (lub z booking_data)
- `_carei_last_name` ← drivers[0].lastName
- `_carei_email` ← drivers[0].email
- `_carei_phone` ← drivers[0].phone
- `_carei_pesel` ← drivers[0].pesel
- `_carei_address` ← JSON encode drivers[0].address
- `_carei_extras` ← JSON encode priceItems
- `_carei_comments` ← comments
- `_carei_status` ← 'nowe'
- `_carei_raw_response` ← JSON encode api_result (backup)
4. **Error handling:** Jeśli wp_insert_post() fail, loguj do error_log ale NIE blokuj response do usera (rezerwacja już w Softra jest OK).
Avoid: Nie modyfikuj flow rezerwacji. Zapis jest fire-and-forget — nigdy nie blokuje odpowiedzi do klienta.
</action>
<verify>
- Złóż testową rezerwację przez formularz
- Sprawdź wp-admin → Rezerwacje → nowy wpis z danymi
- Kliknij wpis → meta box ze szczegółami
</verify>
<done>AC-2 satisfied: rezerwacja zapisuje się automatycznie po sukcesie</done>
</task>
<task type="checkpoint:human-verify" gate="blocking">
<what-built>Admin panel rezerwacji w wp-admin: CPT, kolumny, filtr statusu, meta box szczegółów, auto-zapis po rezerwacji, auto-mark-read</what-built>
<how-to-verify>
1. Otwórz wp-admin na carei.pagedev.pl
2. W menu bocznym: "Rezerwacje" z ikoną samochodu
3. Złóż rezerwację przez formularz na frontendzie
4. Wróć do wp-admin → Rezerwacje → nowy wpis ze statusem "nowe" (niebieski badge)
5. Kolumny: Nr rezerwacji, Klient, Segment, Daty, Oddział, Status, Data
6. Filtr statusu nad listą (dropdown)
7. Kliknij wpis → meta box "Szczegóły rezerwacji" z pełnymi danymi
8. Status zmienił się na "przeczytane" (żółty)
9. Zmień status na "zrealizowane" → Zaktualizuj → zielony badge
</how-to-verify>
<resume-signal>Type "approved" to continue, or describe issues to fix</resume-signal>
</task>
</tasks>
<boundaries>
## DO NOT CHANGE
- wp-content/plugins/carei-reservation/assets/js/carei-reservation.js (Phase 4 stable)
- wp-content/plugins/carei-reservation/assets/css/carei-reservation.css (Phase 4 stable)
- wp-content/plugins/carei-reservation/includes/class-elementor-widget.php (Phase 4 stable)
- wp-content/plugins/carei-reservation/includes/class-softra-api.php (API proxy stable)
- .env (credentials)
## SCOPE LIMITS
- Nie dodawaj eksportu CSV/PDF (przyszły feature)
- Nie dodawaj email notyfikacji (zależy od Softra)
- Nie modyfikuj frontend formularza
- Nie dodawaj REST API endpoints dla admin panelu (nie potrzebne — natywny WP admin)
- Nie twórz custom database table — CPT + post_meta wystarczy dla MVP
</boundaries>
<verification>
Before declaring plan complete:
- [ ] CPT `carei_reservation` zarejestrowany w wp-admin
- [ ] Menu "Rezerwacje" widoczne z ikoną
- [ ] Rezerwacja zapisuje się po sukcesie booking
- [ ] Lista: kolumny Nr, Klient, Segment, Daty, Oddział, Status, Data
- [ ] Filtr statusu działa
- [ ] Meta box ze wszystkimi danymi
- [ ] Auto-mark-read przy otwarciu
- [ ] Zmiana statusu przez dropdown + save
- [ ] Badge kolory: nowe=niebieski, przeczytane=żółty, zrealizowane=zielony
- [ ] Brak regresji w booking flow na frontendzie
</verification>
<success_criteria>
- All 5 acceptance criteria met
- All verification checks pass
- No regressions in frontend booking flow
- Human verification approved on carei.pagedev.pl
</success_criteria>
<output>
After completion, create `.paul/phases/05-admin-panel/05-01-SUMMARY.md`
</output>

View File

@@ -0,0 +1,129 @@
---
phase: 05-admin-panel
plan: 01
subsystem: admin
tags: [wordpress, cpt, post-meta, admin-panel]
requires:
- phase: 03-form-submit-booking
provides: booking flow z reservationId/reservationNo w API response
provides:
- Admin panel CPT carei_reservation w wp-admin
- Automatyczny zapis rezerwacji po sukcesie booking
- Lista z kolumnami, filtr statusu, meta box szczegółów
- System statusów nowe/przeczytane/zrealizowane
affects: []
tech-stack:
added: []
patterns: [CPT + post_meta for data storage, fire-and-forget save, static helper method pattern]
key-files:
created: [includes/class-admin-panel.php]
modified: [includes/class-rest-proxy.php, carei-reservation.php]
key-decisions:
- "CPT + post_meta zamiast custom table — WordPress-native, prostsze dla MVP"
- "Fire-and-forget save — nigdy nie blokuje response do usera"
- "Meta-based status zamiast taxonomy — prosty 3-wartościowy enum"
- "Auto-mark-read on edit — naturalny workflow bez dodatkowych kliknięć"
patterns-established:
- "Static save helper: Carei_Admin_Panel::save_reservation() wywoływany z REST proxy"
- "Inline admin CSS scoped do CPT screen"
duration: ~2h
started: 2026-03-25
completed: 2026-03-25
---
# Phase 5 Plan 01: Admin Panel — Historia Formularzy Summary
**CPT carei_reservation z automatycznym zapisem rezerwacji, listą z kolumnami/filtrami, meta boxem szczegółów i systemem statusów nowe/przeczytane/zrealizowane.**
## Performance
| Metric | Value |
|--------|-------|
| Duration | ~2h |
| Started | 2026-03-25 |
| Completed | 2026-03-25 |
| Tasks | 3 completed (2 auto + 1 human-verify) |
| Files modified | 3 |
## Acceptance Criteria Results
| Criterion | Status | Notes |
|-----------|--------|-------|
| AC-1: CPT carei_reservation zarejestrowany | Pass | Menu "Rezerwacje" z dashicons-car, public: false, show_ui: true |
| AC-2: Rezerwacja zapisuje się automatycznie | Pass | save_reservation() wywoływane po make_booking success |
| AC-3: Lista z kolumnami | Pass | Nr, Klient, Segment, Daty, Oddział, Status, Data + filtr statusu |
| AC-4: Podgląd szczegółów | Pass | Meta box z pełną tabelą danych + dropdown statusu |
| AC-5: Auto-mark-read | Pass | Status "nowe" → "przeczytane" przy otwarciu edycji |
## Accomplishments
- CPT `carei_reservation` z pełnym admin UI: kolumny, filtr, meta box, statusy z kolorowymi badge'ami
- Fire-and-forget zapis rezerwacji po sukcesie booking (nie blokuje response)
- Klikalny nr rezerwacji w liście (link do edycji)
## Files Created/Modified
| File | Change | Purpose |
|------|--------|---------|
| `includes/class-admin-panel.php` | Created | CPT registration, admin columns, meta box, status system, auto-mark-read, save helper |
| `includes/class-rest-proxy.php` | Modified | Wywołanie save_reservation() po udanym make_booking |
| `carei-reservation.php` | Modified | Include + inicjalizacja Carei_Admin_Panel |
## Decisions Made
| Decision | Rationale | Impact |
|----------|-----------|--------|
| CPT + post_meta (nie custom table) | WordPress-native, pełne admin UI za darmo | Prostsze dla MVP, ewentualna migracja jeśli skala wzrośnie |
| Fire-and-forget save | Rezerwacja już w Softra — WP save nie może blokować usera | Bezpieczne — error_log w razie problemu |
| Meta-based status (nie taxonomy) | 3 wartości enum, zero UI overhead | Proste, wystarczające dla MVP |
| Auto-mark-read on edit | Naturalny workflow, mniej kliknięć | UX improvement |
| Klikalny nr rezerwacji | Brak kolumny title = brak linku do edycji | Naprawione podczas checkpoint — link w kolumnie reservation_no |
## Deviations from Plan
### Summary
| Type | Count | Impact |
|------|-------|--------|
| Auto-fixed | 1 | Kliknięcie w rezerwację — minor UX fix |
| Scope additions | 0 | — |
| Deferred | 0 | — |
**Total impact:** Minimalne — jeden fix UX podczas checkpoint
### Auto-fixed Issues
**1. Brak linku do edycji w liście rezerwacji**
- **Found during:** Checkpoint (Task 3)
- **Issue:** Bez kolumny `title` nie było klikalnego linku do szczegółów
- **Fix:** Owinięcie nr rezerwacji w `<a>` z `get_edit_post_link()`
- **Files:** `includes/class-admin-panel.php`
- **Verification:** User potwierdził "Teraz jest ok"
## Issues Encountered
| Issue | Resolution |
|-------|------------|
| Brak linku do edycji rezerwacji | Dodano link w kolumnie reservation_no |
## Next Phase Readiness
**Ready:**
- Milestone v0.1 kompletny — wszystkie 5 faz zakończone
- Plugin w pełni funkcjonalny: formularz → API → admin panel
**Concerns:**
- Brak — MVP complete
**Blockers:**
- None
---
*Phase: 05-admin-panel, Plan: 01*
*Completed: 2026-03-25*