Przeglądaj źródła

fix(docs): update frontend-ui.md for improved clarity and consistency in search scope UX documentation

Code_Uwe 3 tygodni temu
rodzic
commit
11d9f02f90
1 zmienionych plików z 110 dodań i 30 usunięć
  1. 110 30
      Docs/frontend-ui.md

+ 110 - 30
Docs/frontend-ui.md

@@ -1,14 +1,14 @@
 <!-- --------------------------------------------------------------------------- -->
 
-<!-- Ordner: docs -->
+<!-- Folder: docs -->
 
-<!-- Datei: frontend-ui.md -->
+<!-- File: frontend-ui.md -->
 
-<!-- Relativer Pfad: docs/frontend-ui.md -->
+<!-- Relative Path: docs/frontend-ui.md -->
 
 <!-- --------------------------------------------------------------------------- -->
 
-# Frontend UI: App Shell, Routing, Auth/RBAC, Explorer, and Search (RHL-019 / RHL-020 / RHL-021 / RHL-022 / RHL-023 / RHL-024)
+# Frontend UI: App Shell, Routing, Auth/RBAC, Explorer, and Search (RHL-019 / RHL-020 / RHL-021 / RHL-022 / RHL-023 / RHL-024 / RHL-037)
 
 This document describes the **frontend routing scaffold**, the **application shell layout**, and the core UI modules for the RHL Lieferscheine app.
 
@@ -20,6 +20,7 @@ Timeline:
 - **RHL-022**: Explorer v2 (Year → Month → Day → Files) + shadcn Breadcrumbs with dropdowns.
 - **RHL-023**: Explorer file action “Open PDF” using the binary PDF endpoint (opens in a new tab).
 - **RHL-024**: Search UI v1 (URL-driven `q`, scopes, cursor pagination, open PDF + jump to day).
+- **RHL-037**: Search scope UX improvements (TopNav deep-link branch switching + Single combobox + Multi selection UX + deterministic URL state).
 
 > **Language policy**
 >
@@ -31,7 +32,7 @@ Timeline:
 
 ## 1. Scope
 
-### 1.1 Implemented (as of RHL-024)
+### 1.1 Implemented (as of RHL-037)
 
 - **Public** `/login` route with a functional login form (shadcn/ui primitives).
 
@@ -95,7 +96,7 @@ Timeline:
   - Clicking “Öffnen” opens the selected PDF **in a new browser tab**.
   - URL construction is centralized in `lib/frontend/explorer/pdfUrl.js`.
 
-- **Search UI v1 (RHL-024)**
+- **Search UI (RHL-024) + Scope UX improvements (RHL-037)**
 
   - Route: `/:branch/search` (protected).
 
@@ -103,31 +104,37 @@ Timeline:
 
     - `q` (search query)
 
-    - scope params for admin/dev:
+    - scope semantics:
 
-      - single: `branch=NLxx`
-      - multi: `scope=multi&branches=NL06,NL20`
-      - all: `scope=all`
+      - **Single**: route branch is the scope (`/:branch/search`). No `branch=` query parameter is required.
+      - **Multi**: `scope=multi&branches=NL06,NL20` (deterministic order, unique list)
+      - **All**: `scope=all`
 
-    - `limit` (optional): `50 | 100 | 200` (default 100; only included in URL when non-default)
+    - `limit` (optional): `50 | 100 | 200` (default 100)
+
+    - `from/to` are carried through the URL but date-range UI is still planned for later.
 
   - Cursor-based pagination (`nextCursor`) is **not stored in the URL**.
 
-  - Results support:
+  - Admin/dev UX:
+
+    - **TopNav branch switch navigates** (deep-link branch switching):
+
+      - preserves the current deep path (Explorer and Search)
+      - preserves shareable Search query params (`q`, `scope`, `branches`, `limit`, `from`, `to`)
+      - keeps Single scope consistent with the route branch.
 
-    - Open PDF in a new tab (“Öffnen”)
-    - Navigate to the Explorer day route (“Zum Tag”)
+    - **Single scope branch selection** uses a shadcn combobox to switch the _route branch_.
 
-  - Search results UI includes:
+    - **Multi scope branch selection** uses a checkbox grid (optimized for large branch counts) and provides an **“Alle abwählen”** action.
 
-    - Empty/Loading/Error states
-    - Sorting dropdown (Relevanz / Datum / Dateiname)
-    - “Mehr laden” button (cursor pagination)
-    - “x von y” progress indicator when `total` is available
+  - Branch list for admin/dev is fetched via `GET /api/branches` (fail-open).
+
+---
 
 ### 1.2 Still out of scope / planned
 
-- Date range UI for Search (`from` / `to`) and URL sync (planned follow-up after Search UI v1).
+- Date range UI for Search (`from` / `to`) and URL sync (planned follow-up after Search scope UX).
 
 - Optional Search UX improvements:
 
@@ -251,12 +258,31 @@ Purpose:
 Behavior:
 
 - Branch users: QuickNav uses the user’s `branchId`.
+
 - Admin/dev users:
 
   - QuickNav loads branches via `GET /api/branches`.
   - Provides a branch dropdown.
   - Stores the last selected branch in `localStorage` for convenience.
 
+RHL-037 navigation rule:
+
+- When admin/dev selects a branch in QuickNav, the app **navigates** to the same section while replacing the path branch segment:
+
+  - Explorer deep paths are preserved:
+
+    - `/NL32/2025/12/31` → `/NL20/2025/12/31`
+
+  - Search route is preserved and shareable query params are preserved:
+
+    - `/NL32/search?q=x&scope=multi&branches=NL06,NL20&limit=200` → `/NL20/search?q=x&scope=multi&branches=NL06,NL20&limit=200`
+
+  - Single scope is kept consistent with the route branch (no divergence between UI selection and URL).
+
+Implementation note:
+
+- Helper logic for deep-path branch switching is centralized under `lib/frontend/quickNav/branchSwitch.js`.
+
 Responsive behavior:
 
 - QuickNav is hidden on small screens by default (`md` and up only) to keep the header compact.
@@ -469,7 +495,7 @@ Implementation notes:
 
 ---
 
-## 8. Search UI v1 (RHL-024)
+## 8. Search UI (RHL-024) + Scope UX improvements (RHL-037)
 
 ### 8.1 Route and state model
 
@@ -477,7 +503,13 @@ Route:
 
 - `/:branch/search`
 
-State policy:
+Single Source of Truth rule (RHL-037):
+
+- The **path segment** `/:branch/search` is the source of truth for the **current branch context**.
+- Single-scope search uses the **route branch**.
+- Shareable URLs for search do not need to carry `branch=` for Single.
+
+URL-driven state policy:
 
 - Search state is **URL-driven** to support shareable links.
 - Cursor-based pagination state is **not shareable** and is kept in client state.
@@ -488,9 +520,18 @@ Shareable params (first page identity):
 
 - Scope params:
 
-  - single branch: `branch=NLxx`
-  - multi: `scope=multi&branches=NL06,NL20`
-  - all: `scope=all`
+  - **Single**: no `scope` param required; route branch defines the branch.
+
+    - Example: `/NL01/search?q=reifen`
+
+  - **Multi**: `scope=multi&branches=NL06,NL20`
+
+    - branches list is deterministic:
+
+      - unique
+      - stable ordering
+
+  - **All**: `scope=all`
 
 - `limit`:
 
@@ -498,6 +539,11 @@ Shareable params (first page identity):
   - default: `100`
   - only written to URL when non-default to keep URLs readable
 
+- `from/to`:
+
+  - carried through the URL to prepare for the date-range UI
+  - date-range UI is still planned
+
 Pagination:
 
 - `nextCursor` is kept in client state.
@@ -514,15 +560,28 @@ Admin/dev users:
 
 - Scope selector:
 
-  - “Diese Niederlassung” (single branch route context)
+  - “Diese Niederlassung” (single: route branch)
   - “Mehrere Niederlassungen” (multi)
   - “Alle Niederlassungen” (all)
 
+- Single branch selection:
+
+  - shadcn combobox
+  - selecting a branch **navigates** to `/:branch/search` while preserving shareable query params (`q`, scope params, `limit`, `from/to`).
+
 - Multi branch selection:
 
-  - simple checkbox list
-  - branch list is fetched from `GET /api/branches`
-  - fail-open behavior: if branch list cannot be loaded, the rest of the Search UI remains usable
+  - checkbox grid optimized for large branch counts
+  - 5 columns on desktop (`md:grid-cols-5`)
+  - optional “Alle abwählen” button to reset selection
+
+- Branch list:
+
+  - loaded via `GET /api/branches`
+  - fail-open UI behavior:
+
+    - if branch list fails, Search UI remains usable
+    - (optional fallback) allow manual NLxx input for selection
 
 ### 8.3 Result list and actions
 
@@ -575,6 +634,10 @@ Key outcomes:
 - `VALIDATION_*` → show a user-friendly German validation message
 - network/unknown → generic German error + retry
 
+UX note (RHL-037):
+
+- Multi scope with a query but zero branches selected is treated as “not ready” and shows a friendly hint.
+
 ---
 
 ## 9. UI primitives (shadcn/ui)
@@ -593,6 +656,12 @@ Required components for the current scope:
 - `skeleton`
 - `table`
 
+Additional primitives used for Search scope UX:
+
+- `popover`
+- `command`
+- `badge`
+
 ---
 
 ## 10. File Naming Convention (.js vs .jsx)
@@ -645,6 +714,10 @@ Search helper tests:
 - `lib/frontend/search/searchApiInput.test.js`
 - `lib/frontend/search/resultsSorting.test.js`
 
+QuickNav helper tests:
+
+- `lib/frontend/quickNav/branchSwitch.test.js`
+
 Component SSR smoke test:
 
 - `components/app-shell/AppShell.test.js`
@@ -717,13 +790,19 @@ Search checks:
 - admin/dev:
 
   - scope switching (single/multi/all)
-  - multi selection (checkboxes)
+  - single branch selection via combobox
+  - multi selection via checkbox grid + “Alle abwählen”
   - limit switching (50/100/200)
 
 - pagination:
 
   - “Mehr laden” appends results when `nextCursor` exists
 
+- TopNav QuickNav:
+
+  - switching branch updates the URL and keeps the current deep path
+  - switching branch on Search keeps shareable query params
+
 ### 12.2 Server
 
 Deploy and verify on the server URL.
@@ -737,6 +816,7 @@ Verify:
   - limit selection
   - total count (“x von y geladen”)
   - open PDF / jump to day
+  - TopNav branch switching keeps deep links
 
 ---