This commit is contained in:
2026-04-07 20:32:43 +02:00
parent 1933c74395
commit 8fa9ca6439
45 changed files with 2974 additions and 3382 deletions

View File

@@ -0,0 +1,207 @@
---
phase: 81-global-search-bar
plan: 01
type: execute
wave: 1
depends_on: []
files_modified: [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]
autonomous: true
---
<objective>
## 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
</objective>
<context>
## 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)
</context>
<acceptance_criteria>
## AC-1: Pole wyszukiwania widoczne w topbarze
```gherkin
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
```gherkin
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
```gherkin
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
```gherkin
Given dropdown z wynikami jest widoczny
When uzytkownik klika na wynik
Then zostaje przeniesiony do /orders/{id} (strona szczegulow zamowienia)
```
## AC-5: Nawigacja klawiaturowa
```gherkin
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
```gherkin
Given dropdown z wynikami jest widoczny
When uzytkownik klika poza polem wyszukiwania i dropdownem
Then dropdown sie zamyka
```
</acceptance_criteria>
<tasks>
<task type="auto">
<name>Task 1: Backend — endpoint quickSearch</name>
<files>src/Modules/Orders/OrdersRepository.php, src/Modules/Orders/OrdersController.php, routes/web.php</files>
<action>
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)
</action>
<verify>
Recznie wywolac GET /api/orders/search?q=test z przegladarki (zalogowany) — odpowiedz JSON z results array
</verify>
<done>AC-2 (backend), AC-3 (dane wynikow) spelnione</done>
</task>
<task type="auto">
<name>Task 2: Frontend — search bar w topbarze + JS + SCSS</name>
<files>resources/views/layouts/app.php, public/assets/js/modules/global-search.js, resources/scss/components/_global-search.scss, resources/scss/app.scss</files>
<action>
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)
</action>
<verify>
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
</verify>
<done>AC-1, AC-2 (frontend), AC-3, AC-4, AC-5, AC-6 spelnione</done>
</task>
</tasks>
<boundaries>
## 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
</boundaries>
<verification>
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
</verification>
<success_criteria>
- Oba taski ukonczone
- Wszystkie verification checks przechodzą
- Brak regresji w istniejacym UI
</success_criteria>
<output>
After completion, create `.paul/phases/81-global-search-bar/81-01-SUMMARY.md`
</output>

View File

@@ -0,0 +1,98 @@
---
phase: 81-global-search-bar
plan: 01
subsystem: ui
tags: [javascript, ajax, search, orders, topbar]
requires:
- phase: 44-inline-status-change
provides: orders list infrastructure
provides:
- global search bar in topbar
- GET /api/orders/search endpoint
- keyboard-navigable search dropdown
affects: []
tech-stack:
added: []
patterns: [debounced AJAX search with dropdown results]
key-files:
created: [public/assets/js/modules/global-search.js, resources/scss/modules/_global-search.scss]
modified: [src/Modules/Orders/OrdersRepository.php, src/Modules/Orders/OrdersController.php, routes/web.php, resources/views/layouts/app.php, resources/scss/app.scss, public/assets/css/app.css]
key-decisions: []
patterns-established:
- "Global search: debounced AJAX fetch to /api/orders/search with dropdown rendering"
duration: 5min
started: 2026-04-07T00:00:00Z
completed: 2026-04-07T00:00:00Z
---
# Phase 81 Plan 01: Global Search Bar Summary
**Globalna wyszukiwarka zamowien w topbarze — AJAX search z debounce, dropdown wynikow, nawigacja klawiaturowa, przeszukiwanie po numerze/nazwisku/email/telefonie/produkcie.**
## Performance
| Metric | Value |
|--------|-------|
| Duration | 5min |
| Tasks | 2 completed |
| Files modified | 8 |
## Acceptance Criteria Results
| Criterion | Status | Notes |
|-----------|--------|-------|
| AC-1: Pole wyszukiwania w topbarze | Pass | Input miedzy hamburgerem a user info |
| AC-2: Wyszukiwanie AJAX z debounce | Pass | 300ms debounce, min 2 znaki |
| AC-3: Wyniki wyszukiwania | Pass | Numer, nazwisko, email, telefon; max 10; "Brak wynikow" |
| AC-4: Nawigacja do zamowienia | Pass | Klik na wynik → /orders/{id} |
| AC-5: Nawigacja klawiaturowa | Pass | ArrowUp/Down, Enter, Escape |
| AC-6: Zamykanie dropdowna | Pass | Klik poza zamyka |
## Accomplishments
- Nowy endpoint `GET /api/orders/search?q=...&limit=10` z prepared statements
- Metoda `quickSearch()` w OrdersRepository szuka po 6 polach (source_order_id, external_order_id, name, email, phone, product name)
- Modul JS global-search.js z debounce, dropdown, nawigacja klawiaturowa
- Responsywne style SCSS
## Files Created/Modified
| File | Change | Purpose |
|------|--------|---------|
| `src/Modules/Orders/OrdersRepository.php` | Modified | Nowa metoda `quickSearch()` |
| `src/Modules/Orders/OrdersController.php` | Modified | Nowa metoda `quickSearch()` |
| `routes/web.php` | Modified | Route GET /api/orders/search |
| `resources/views/layouts/app.php` | Modified | Pole wyszukiwania w topbarze + script include |
| `public/assets/js/modules/global-search.js` | Created | Modul JS (debounce, dropdown, klawiatura) |
| `resources/scss/modules/_global-search.scss` | Created | Style komponentu wyszukiwarki |
| `resources/scss/app.scss` | Modified | Import nowego modulu SCSS |
| `public/assets/css/app.css` | Modified | Zbudowany CSS |
## Deviations from Plan
None — plan executed exactly as written.
## Issues Encountered
None.
## Next Phase Readiness
**Ready:**
- Wyszukiwarka globalna dziala na kazdej stronie
**Concerns:**
- None
**Blockers:**
- None
---
*Phase: 81-global-search-bar, Plan: 01*
*Completed: 2026-04-07*