Files
orderPRO/.paul/phases/81-global-search-bar/81-01-PLAN.md
2026-04-07 20:32:43 +02:00

8.8 KiB

phase, plan, type, wave, depends_on, files_modified, autonomous
phase plan type wave depends_on files_modified autonomous
81-global-search-bar 01 execute 1
src/Modules/Orders/OrdersRepository.php
src/Modules/Orders/OrdersController.php
routes/web.php
resources/views/layouts/app.php
public/assets/js/modules/global-search.js
resources/scss/components/_global-search.scss
resources/scss/app.scss
true
## Goal Globalna wyszukiwarka zamowien widoczna w topbarze na kazdej stronie orderPRO. Wyszukuje po: numerze zamowienia, nazwisku klienta, e-mailu, telefonie, nazwie produktu. Wyniki pojawiaja sie jako dropdown pod polem wyszukiwania. Klikniecie wyniku przenosi do /orders/{id}.

Purpose

Szybki dostep do zamowienia z dowolnego miejsca w aplikacji — bez koniecznosci przechodzenia na liste zamowien i ustawiania filtrow. Analogicznie do wyszukiwarki w shopPRO.

Output

  • Nowy endpoint GET /api/orders/search?q=...&limit=10
  • Pole wyszukiwania w topbarze (layout app.php)
  • Modul JS global-search.js (debounced AJAX, dropdown wynikow, nawigacja klawiaturowa)
  • Style SCSS dla komponentu wyszukiwarki
## Project Context @.paul/PROJECT.md @.paul/ROADMAP.md @.paul/STATE.md

Source Files

@src/Modules/Orders/OrdersRepository.php (linie 91-106 — istniejacy search SQL) @src/Modules/Orders/OrdersController.php (index() linie 44-71) @routes/web.php (linie 408-413 — order routes) @resources/views/layouts/app.php (linie 121-136 — topbar)

<acceptance_criteria>

AC-1: Pole wyszukiwania widoczne w topbarze

Given uzytkownik jest zalogowany i na dowolnej stronie orderPRO
When strona sie laduje
Then w topbarze widoczne jest pole wyszukiwania z placeholderem "Szukaj zamowien..."
And pole jest miedzy hamburgerem a sekcja uzytkownika

AC-2: Wyszukiwanie AJAX z debounce

Given uzytkownik wpisuje tekst w pole wyszukiwania (min. 2 znaki)
When minie 300ms od ostatniego znaku (debounce)
Then wykonywane jest zapytanie GET /api/orders/search?q=tekst&limit=10
And pod polem pojawia sie dropdown z wynikami

AC-3: Wyniki wyszukiwania

Given backend znalazl pasujace zamowienia
When dropdown jest wyswietlany
Then kazdy wynik pokazuje: numer zamowienia, nazwe klienta, e-mail, telefon
And wyniki sa ograniczone do max 10
And jesli brak wynikow, wyswietla "Brak wynikow"

AC-4: Nawigacja do zamowienia

Given dropdown z wynikami jest widoczny
When uzytkownik klika na wynik
Then zostaje przeniesiony do /orders/{id} (strona szczegulow zamowienia)

AC-5: Nawigacja klawiaturowa

Given dropdown z wynikami jest widoczny
When uzytkownik uzywa strzalek gora/dol
Then podswietlony wynik sie zmienia
When uzytkownik naciska Enter na podswietlonym wyniku
Then zostaje przeniesiony do /orders/{id}
When uzytkownik naciska Escape
Then dropdown sie zamyka

AC-6: Zamykanie dropdowna

Given dropdown z wynikami jest widoczny
When uzytkownik klika poza polem wyszukiwania i dropdownem
Then dropdown sie zamyka

</acceptance_criteria>

Task 1: Backend — endpoint quickSearch src/Modules/Orders/OrdersRepository.php, src/Modules/Orders/OrdersController.php, routes/web.php 1. W `OrdersRepository.php` dodac metode `quickSearch(string $query, int $limit = 10): array`: - SQL: SELECT o.id, o.source_order_id, o.external_order_id, a.name AS buyer_name, a.email AS buyer_email, a.phone AS buyer_phone - FROM orders o LEFT JOIN order_addresses a ON a.order_id = o.id AND a.address_type = 'customer' - WHERE (o.source_order_id LIKE :s OR o.external_order_id LIKE :s OR a.name LIKE :s OR a.email LIKE :s OR a.phone LIKE :s OR EXISTS (SELECT 1 FROM order_items oi WHERE oi.order_id = o.id AND oi.original_name LIKE :s)) - ORDER BY o.ordered_at DESC LIMIT :limit - Uzyc prepared statements (Medoo raw lub PDO) - Zwracac tablice z id, order_number (source_order_id lub external_order_id), buyer_name, buyer_email, buyer_phone
2. W `OrdersController.php` dodac metode `quickSearch(Request $request): Response`:
   - Pobrac q = $request->input('q', '') — jesli pusty lub < 2 znaki, zwrocic pusty JSON []
   - Pobrac limit = min((int)$request->input('limit', 10), 20)
   - Wywolac $this->orders->quickSearch($q, $limit)
   - Zwrocic Response::json(['results' => $results])
   - Sprawdzic header X-Requested-With = XMLHttpRequest (opcjonalne, ale dobre praktyki)

3. W `routes/web.php` dodac route:
   - $router->get('/api/orders/search', [$ordersController, 'quickSearch'], [$authMiddleware]);
   - Dodac po istniejacych order routes (po linii ~413)
Recznie wywolac GET /api/orders/search?q=test z przegladarki (zalogowany) — odpowiedz JSON z results array AC-2 (backend), AC-3 (dane wynikow) spelnione Task 2: Frontend — search bar w topbarze + JS + SCSS resources/views/layouts/app.php, public/assets/js/modules/global-search.js, resources/scss/components/_global-search.scss, resources/scss/app.scss 1. W `resources/views/layouts/app.php` w topbarze (miedzy hamburgerem a sekcja uzytkownika): - Dodac div.global-search z: - input type="text" z id="js-global-search" placeholder="Szukaj zamowien..." autocomplete="off" - div.global-search__results (pusty, do wynikow) - Na dole strony (przed zamknieciem body) dodac script include dla global-search.js
2. Stworzyc `public/assets/js/modules/global-search.js`:
   - IIFE, 'use strict'
   - Debounce 300ms na input event
   - Min. 2 znaki do wyszukiwania
   - Fetch GET /api/orders/search?q=...&limit=10 z header X-Requested-With: XMLHttpRequest
   - Renderowanie wynikow w .global-search__results:
     - Kazdy wynik: link <a href="/orders/{id}"> z numerem zamowienia, nazwiskiem, emailem, telefonem
     - Jesli brak wynikow: div "Brak wynikow"
   - Nawigacja klawiaturowa: ArrowDown/ArrowUp zmienia podswietlenie, Enter nawiguje, Escape zamyka
   - Klik poza komponentem zamyka dropdown (document click listener)
   - Przy pustym/krotkim query — zamknij dropdown

3. Stworzyc `resources/scss/components/_global-search.scss`:
   - .global-search: flex: 1, max-width: 500px, position: relative, margin: 0 1rem
   - .global-search input: szerokosc 100%, border-radius, padding, font-size
   - .global-search__results: position absolute, top 100%, left 0, width 100%, background white, border, border-radius, box-shadow, max-height 400px, overflow-y auto, z-index 1000
   - .global-search__item: padding, cursor pointer, border-bottom, hover/active background
   - .global-search__item.is-highlighted: background podswietlenia
   - .global-search__item-title: font-weight bold (numer zamowienia)
   - .global-search__item-details: font-size mniejszy, color szary (nazwisko, email, telefon)
   - .global-search__empty: padding, text-align center, color szary
   - Responsywnosc: na mobile input moze byc mniejszy lub ikona lupa rozwijajaca pole

4. W `resources/scss/app.scss` dodac @import 'components/global-search'

5. Zbudowac SCSS do CSS (jesli istnieje build command)
1. Otworz dowolna strone orderPRO — pole wyszukiwania widoczne w topbarze 2. Wpisz nazwe klienta — po 300ms dropdown z wynikami 3. Kliknij wynik — przeniesienie do /orders/{id} 4. Strzalki gora/dol + Enter — nawigacja klawiaturowa 5. Escape lub klik poza — zamkniecie dropdowna AC-1, AC-2 (frontend), AC-3, AC-4, AC-5, AC-6 spelnione

DO NOT CHANGE

  • src/Modules/Orders/OrdersRepository.php — istniejaca metoda paginate() i buildPaginateFilters() (nie modyfikowac)
  • resources/views/orders/list.php — istniejaca wyszukiwarka na liscie zamowien
  • public/assets/js/modules/inline-status-change.js
  • database/migrations/*

SCOPE LIMITS

  • Wyszukiwanie TYLKO zamowien (nie produktow — nie ma jeszcze modulu produktow w orderPRO)
  • Brak historii wyszukiwan
  • Brak cache wynikow
  • Nie zmieniac istniejacego wyszukiwania na liscie zamowien
Before declaring plan complete: - [ ] GET /api/orders/search?q=test zwraca JSON z wynikami - [ ] Pole wyszukiwania widoczne w topbarze na kazdej stronie - [ ] Dropdown wynikow pojawia sie po wpisaniu 2+ znakow - [ ] Klikniecie wyniku przenosi do /orders/{id} - [ ] Nawigacja klawiaturowa (strzalki, Enter, Escape) dziala - [ ] Klik poza zamyka dropdown - [ ] Na mobile pole wyszukiwania nie psuje layoutu topbara

<success_criteria>

  • Oba taski ukonczone
  • Wszystkie verification checks przechodzą
  • Brak regresji w istniejacym UI </success_criteria>
After completion, create `.paul/phases/81-global-search-bar/81-01-SUMMARY.md`