--- 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 --- ## 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) ## 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 ## 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ę ``` Task 1: CPT registration + admin panel class wp-content/plugins/carei-reservation/includes/class-admin-panel.php, wp-content/plugins/carei-reservation/carei-reservation.php 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. - Otwórz wp-admin → "Rezerwacje" widoczne w menu - Lista pusta, kolumny widoczne - Filtr statusu nad listą AC-1, AC-3, AC-4, AC-5 satisfied: CPT zarejestrowany, kolumny, meta box, auto-read Task 2: Zapis rezerwacji po sukcesie booking wp-content/plugins/carei-reservation/includes/class-rest-proxy.php 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. - Złóż testową rezerwację przez formularz - Sprawdź wp-admin → Rezerwacje → nowy wpis z danymi - Kliknij wpis → meta box ze szczegółami AC-2 satisfied: rezerwacja zapisuje się automatycznie po sukcesie Admin panel rezerwacji w wp-admin: CPT, kolumny, filtr statusu, meta box szczegółów, auto-zapis po rezerwacji, auto-mark-read 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 Type "approved" to continue, or describe issues to fix ## 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 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 - All 5 acceptance criteria met - All verification checks pass - No regressions in frontend booking flow - Human verification approved on carei.pagedev.pl After completion, create `.paul/phases/05-admin-panel/05-01-SUMMARY.md`