|
@@ -1,4 +1,4 @@
|
|
|
-# Frontend UI: App Shell, Routing, Auth/RBAC, Explorer, Search, Date Range Filter, Navigation Polish, Profile Password Change, and Role Refinement (RHL-019 / RHL-020 / RHL-021 / RHL-022 / RHL-023 / RHL-024 / RHL-025 / RHL-037 / RHL-032 / RHL-009 / RHL-041)
|
|
|
|
|
|
|
+# Frontend UI: App Shell, Routing, Auth/RBAC, Explorer, Search, Date Range Filter, Navigation Polish, Profile Password Change, User Management, and Role Refinement (RHL-019 / RHL-020 / RHL-021 / RHL-022 / RHL-023 / RHL-024 / RHL-025 / RHL-037 / RHL-032 / RHL-009 / RHL-012 / RHL-041)
|
|
|
|
|
|
|
|
This document describes the **frontend routing scaffold**, the **application shell layout**, and the core UI modules for the RHL Lieferscheine app.
|
|
This document describes the **frontend routing scaffold**, the **application shell layout**, and the core UI modules for the RHL Lieferscheine app.
|
|
|
|
|
|
|
@@ -14,7 +14,8 @@ Timeline:
|
|
|
- **RHL-037**: Search scope UX improvements (TopNav deep-link branch switching + Single combobox + Multi selection UX + deterministic URL state).
|
|
- **RHL-037**: Search scope UX improvements (TopNav deep-link branch switching + Single combobox + Multi selection UX + deterministic URL state).
|
|
|
- **RHL-032**: Navigation UX polish (TopNav branding, theme toggle, user menu, tooltips, session indicator without content flicker, favicon, active states, and debounced loading UI).
|
|
- **RHL-032**: Navigation UX polish (TopNav branding, theme toggle, user menu, tooltips, session indicator without content flicker, favicon, active states, and debounced loading UI).
|
|
|
- **RHL-009**: Profile password change UI (Change Password form + toasts).
|
|
- **RHL-009**: Profile password change UI (Change Password form + toasts).
|
|
|
-- **RHL-041**: Role refinement (`superadmin`) + capability separation for future user management (RHL-012).
|
|
|
|
|
|
|
+- **RHL-041**: Role refinement (`superadmin`) + capability separation (branch access vs user management).
|
|
|
|
|
+- **RHL-012**: User management UI (list/create/update/delete users) + guarded admin endpoints.
|
|
|
|
|
|
|
|
> **Language policy**
|
|
> **Language policy**
|
|
|
>
|
|
>
|
|
@@ -26,7 +27,7 @@ Timeline:
|
|
|
|
|
|
|
|
## 1. Scope
|
|
## 1. Scope
|
|
|
|
|
|
|
|
-### 1.1 Implemented (as of RHL-041 + RHL-037 + RHL-025 + RHL-032 + RHL-009)
|
|
|
|
|
|
|
+### 1.1 Implemented (as of RHL-012 + RHL-041 + RHL-037 + RHL-025 + RHL-032 + RHL-009)
|
|
|
|
|
|
|
|
- **Public** `/login` route with a functional login form (shadcn/ui primitives).
|
|
- **Public** `/login` route with a functional login form (shadcn/ui primitives).
|
|
|
|
|
|
|
@@ -47,7 +48,7 @@ Timeline:
|
|
|
- Logout action calls `GET /api/auth/logout` and redirects to `/login?reason=logged-out`.
|
|
- Logout action calls `GET /api/auth/logout` and redirects to `/login?reason=logged-out`.
|
|
|
|
|
|
|
|
- **User dropdown menu (RHL-032)**:
|
|
- **User dropdown menu (RHL-032)**:
|
|
|
- - Profile / Support / Logout
|
|
|
|
|
|
|
+ - Profil / (optional) Benutzerverwaltung / Support / Abmelden
|
|
|
|
|
|
|
|
- **Profile password change (RHL-009)**:
|
|
- **Profile password change (RHL-009)**:
|
|
|
- Route: `/profile` (protected)
|
|
- Route: `/profile` (protected)
|
|
@@ -66,7 +67,20 @@ Timeline:
|
|
|
- UI introduces a pure role helper:
|
|
- UI introduces a pure role helper:
|
|
|
- `lib/frontend/auth/roles.js`
|
|
- `lib/frontend/auth/roles.js`
|
|
|
- `isAdminLike(role)` → `admin | superadmin | dev`
|
|
- `isAdminLike(role)` → `admin | superadmin | dev`
|
|
|
- - `canManageUsers(role)` → `superadmin | dev` (RHL-012 prerequisite, no UI screens yet)
|
|
|
|
|
|
|
+ - `canManageUsers(role)` → `superadmin | dev`
|
|
|
|
|
+
|
|
|
|
|
+- **User management UI (RHL-012)**:
|
|
|
|
|
+ - Route: `/admin/users` (protected)
|
|
|
|
|
+ - Permission gating:
|
|
|
|
|
+ - allowed: `superadmin`, `dev`
|
|
|
|
|
+ - forbidden: `admin`, `branch`
|
|
|
|
|
+
|
|
|
|
|
+ - Features (v1):
|
|
|
|
|
+ - list users with filters (username/email search, role, branchId)
|
|
|
|
|
+ - create user dialog (initial password + must-change-password flag on create)
|
|
|
|
|
+ - update user (role/branchId consistency enforced)
|
|
|
|
|
+ - delete user
|
|
|
|
|
+ - cursor-based pagination (“Mehr laden”)
|
|
|
|
|
|
|
|
- **UI RBAC (branch-level)**:
|
|
- **UI RBAC (branch-level)**:
|
|
|
- `BranchGuard` prevents branch users from accessing other branches’ URLs.
|
|
- `BranchGuard` prevents branch users from accessing other branches’ URLs.
|
|
@@ -117,7 +131,7 @@ Timeline:
|
|
|
- Solid header (no blur/transparency) for crisp borders.
|
|
- Solid header (no blur/transparency) for crisp borders.
|
|
|
- Branding logo (light + dark assets).
|
|
- Branding logo (light + dark assets).
|
|
|
- Icon-only theme toggle.
|
|
- Icon-only theme toggle.
|
|
|
- - User dropdown menu (Profile / Support / Logout).
|
|
|
|
|
|
|
+ - User dropdown menu (Profil / Benutzerverwaltung\* / Support / Abmelden).
|
|
|
- Consistent tooltips across navigation.
|
|
- Consistent tooltips across navigation.
|
|
|
- Session check indicator in TopNav (debounced) to avoid content flicker.
|
|
- Session check indicator in TopNav (debounced) to avoid content flicker.
|
|
|
- Clear active states for Explorer and Search.
|
|
- Clear active states for Explorer and Search.
|
|
@@ -126,14 +140,12 @@ Timeline:
|
|
|
Implementation note:
|
|
Implementation note:
|
|
|
- For small static brand assets (logos), Next Image optimization is disabled (`unoptimized`) to avoid browser-specific “pending” indicators caused by aborted `/_next/image` optimization requests.
|
|
- For small static brand assets (logos), Next Image optimization is disabled (`unoptimized`) to avoid browser-specific “pending” indicators caused by aborted `/_next/image` optimization requests.
|
|
|
|
|
|
|
|
|
|
+ - The “Benutzerverwaltung” entry is only shown when the user has the user-management capability.
|
|
|
|
|
+
|
|
|
---
|
|
---
|
|
|
|
|
|
|
|
### 1.2 Still out of scope / planned
|
|
### 1.2 Still out of scope / planned
|
|
|
|
|
|
|
|
-- User management UI + APIs (RHL-012):
|
|
|
|
|
- - The UI role helpers already define `canManageUsers(role)`.
|
|
|
|
|
- - RHL-012 will add screens and API endpoints and must enforce `superadmin/dev`.
|
|
|
|
|
-
|
|
|
|
|
- Email-based password reset/recovery:
|
|
- Email-based password reset/recovery:
|
|
|
- Planned as a separate follow-up ticket/phase.
|
|
- Planned as a separate follow-up ticket/phase.
|
|
|
- Rationale: higher security surface (token handling and non-leakage), external SMTP/IT dependencies, and separate rate limiting ticket (RHL-031) to avoid scope creep.
|
|
- Rationale: higher security surface (token handling and non-leakage), external SMTP/IT dependencies, and separate rate limiting ticket (RHL-031) to avoid scope creep.
|
|
@@ -147,6 +159,14 @@ Timeline:
|
|
|
- add a dedicated “Herunterladen” UI action (download variant)
|
|
- add a dedicated “Herunterladen” UI action (download variant)
|
|
|
- optional in-app PDF viewer experience (instead of a new tab)
|
|
- optional in-app PDF viewer experience (instead of a new tab)
|
|
|
|
|
|
|
|
|
|
+- User management UX hardening (separate follow-up ticket):
|
|
|
|
|
+ - delete with explicit username confirmation
|
|
|
|
|
+ - branch user creation UX (fixed `NL` prefix + numeric-only input)
|
|
|
|
|
+ - optional branch existence check / warning when creating branch users
|
|
|
|
|
+
|
|
|
|
|
+- `mustChangePassword` enforcement (separate follow-up ticket):
|
|
|
|
|
+ - gate/redirect until password change is completed
|
|
|
|
|
+
|
|
|
---
|
|
---
|
|
|
|
|
|
|
|
## 2. Route Groups & URL Structure
|
|
## 2. Route Groups & URL Structure
|
|
@@ -172,6 +192,7 @@ The app uses Next.js App Router **Route Groups** to separate public and protecte
|
|
|
| `/login` | Login page | Supports `reason` and `next` query params |
|
|
| `/login` | Login page | Supports `reason` and `next` query params |
|
|
|
| `/` | Protected entry placeholder | Rendered only when authenticated |
|
|
| `/` | Protected entry placeholder | Rendered only when authenticated |
|
|
|
| `/profile` | Profile | Password change is implemented here (RHL-009) |
|
|
| `/profile` | Profile | Password change is implemented here (RHL-009) |
|
|
|
|
|
+| `/admin/users` | Benutzerverwaltung | Only `superadmin`/`dev` (RHL-012) |
|
|
|
| `/:branch` | Explorer: years | Example: `/NL01` |
|
|
| `/:branch` | Explorer: years | Example: `/NL01` |
|
|
|
| `/:branch/:year` | Explorer: months | Example: `/NL01/2025` |
|
|
| `/:branch/:year` | Explorer: months | Example: `/NL01/2025` |
|
|
|
| `/:branch/:year/:month` | Explorer: days | Example: `/NL01/2025/12` |
|
|
| `/:branch/:year/:month` | Explorer: days | Example: `/NL01/2025/12` |
|
|
@@ -265,7 +286,7 @@ Layout groups (left → right):
|
|
|
- **Brand**: logo link to `/` (light + dark variants).
|
|
- **Brand**: logo link to `/` (light + dark variants).
|
|
|
- **Primary navigation**: QuickNav (branch selector + Explorer/Search buttons).
|
|
- **Primary navigation**: QuickNav (branch selector + Explorer/Search buttons).
|
|
|
- **Actions**: theme toggle + session indicator.
|
|
- **Actions**: theme toggle + session indicator.
|
|
|
-- **User menu**: dropdown trigger (Profile / Support / Logout).
|
|
|
|
|
|
|
+- **User menu**: dropdown trigger (Profil / Benutzerverwaltung / Support / Abmelden).
|
|
|
|
|
|
|
|
Design note:
|
|
Design note:
|
|
|
|
|
|
|
@@ -316,6 +337,7 @@ File: `components/app-shell/UserStatus.jsx`
|
|
|
Menu items (German):
|
|
Menu items (German):
|
|
|
|
|
|
|
|
- **Profil** → `/profile` (account info + password change)
|
|
- **Profil** → `/profile` (account info + password change)
|
|
|
|
|
+- **Benutzerverwaltung** → `/admin/users` (only `superadmin` / `dev`)
|
|
|
- **Support** → opens a `mailto:` link to support.
|
|
- **Support** → opens a `mailto:` link to support.
|
|
|
- **Abmelden** → calls logout and redirects to login.
|
|
- **Abmelden** → calls logout and redirects to login.
|
|
|
|
|
|
|
@@ -627,13 +649,43 @@ The project uses Sonner (shadcn/ui integration) for toast notifications.
|
|
|
|
|
|
|
|
---
|
|
---
|
|
|
|
|
|
|
|
-## 11. Profile: Password change (RHL-009)
|
|
|
|
|
|
|
+## 11. User management UI (RHL-012)
|
|
|
|
|
|
|
|
### 11.1 Route
|
|
### 11.1 Route
|
|
|
|
|
|
|
|
|
|
+- `/admin/users` (protected)
|
|
|
|
|
+
|
|
|
|
|
+### 11.2 Authorization
|
|
|
|
|
+
|
|
|
|
|
+- UI gating uses `canManageUsers(role)` from `lib/frontend/auth/roles.js`.
|
|
|
|
|
+- Backend is authoritative:
|
|
|
|
|
+ - all user management APIs require `requireUserManagement(session)`.
|
|
|
|
|
+
|
|
|
|
|
+### 11.3 UI components
|
|
|
|
|
+
|
|
|
|
|
+Files:
|
|
|
|
|
+
|
|
|
|
|
+- `components/admin/users/AdminUsersPage.jsx` (gating)
|
|
|
|
|
+- `components/admin/users/AdminUsersClient.jsx` (list + filters + actions)
|
|
|
|
|
+- `components/admin/users/UsersTable.jsx` (table)
|
|
|
|
|
+- `components/admin/users/CreateUserDialog.jsx` + `components/admin/users/create-user/*` (create flow)
|
|
|
|
|
+
|
|
|
|
|
+The UI uses the API client wrappers from `lib/frontend/apiClient.js`:
|
|
|
|
|
+
|
|
|
|
|
+- `adminListUsers`
|
|
|
|
|
+- `adminCreateUser`
|
|
|
|
|
+- `adminUpdateUser`
|
|
|
|
|
+- `adminDeleteUser`
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 12. Profile: Password change (RHL-009)
|
|
|
|
|
+
|
|
|
|
|
+### 12.1 Route
|
|
|
|
|
+
|
|
|
- `/profile` (protected)
|
|
- `/profile` (protected)
|
|
|
|
|
|
|
|
-### 11.2 Components
|
|
|
|
|
|
|
+### 12.2 Components
|
|
|
|
|
|
|
|
- `components/profile/ProfilePage.jsx`
|
|
- `components/profile/ProfilePage.jsx`
|
|
|
- Shows read-only account/session info (role, branch, email).
|
|
- Shows read-only account/session info (role, branch, email).
|
|
@@ -644,13 +696,13 @@ The project uses Sonner (shadcn/ui integration) for toast notifications.
|
|
|
|
|
|
|
|
---
|
|
---
|
|
|
|
|
|
|
|
-## 12. UI primitives (shadcn/ui)
|
|
|
|
|
|
|
+## 13. UI primitives (shadcn/ui)
|
|
|
|
|
|
|
|
The Explorer + auth + search UI uses shadcn/ui primitives from `components/ui/*`.
|
|
The Explorer + auth + search UI uses shadcn/ui primitives from `components/ui/*`.
|
|
|
|
|
|
|
|
---
|
|
---
|
|
|
|
|
|
|
|
-## 13. File Naming Convention (.js vs .jsx)
|
|
|
|
|
|
|
+## 14. File Naming Convention (.js vs .jsx)
|
|
|
|
|
|
|
|
To keep the project consistent:
|
|
To keep the project consistent:
|
|
|
|
|
|
|
@@ -659,9 +711,9 @@ To keep the project consistent:
|
|
|
|
|
|
|
|
---
|
|
---
|
|
|
|
|
|
|
|
-## 14. Tests
|
|
|
|
|
|
|
+## 15. Tests
|
|
|
|
|
|
|
|
-### 14.1 Unit tests
|
|
|
|
|
|
|
+### 15.1 Unit tests
|
|
|
|
|
|
|
|
Role helper tests (RHL-041):
|
|
Role helper tests (RHL-041):
|
|
|
|
|
|
|
@@ -669,7 +721,7 @@ Role helper tests (RHL-041):
|
|
|
|
|
|
|
|
Existing tests remain as documented in the project.
|
|
Existing tests remain as documented in the project.
|
|
|
|
|
|
|
|
-### 14.2 Running tests
|
|
|
|
|
|
|
+### 15.2 Running tests
|
|
|
|
|
|
|
|
From the repo root:
|
|
From the repo root:
|
|
|
|
|
|
|
@@ -685,27 +737,33 @@ npm run build
|
|
|
|
|
|
|
|
---
|
|
---
|
|
|
|
|
|
|
|
-## 15. Manual verification checklist
|
|
|
|
|
|
|
+## 16. Manual verification checklist
|
|
|
|
|
|
|
|
-### 15.1 Local (Docker)
|
|
|
|
|
|
|
+### 16.1 Local (Docker)
|
|
|
|
|
|
|
|
- Login and verify TopNav role label per account.
|
|
- Login and verify TopNav role label per account.
|
|
|
- Branch switching for admin-like users.
|
|
- Branch switching for admin-like users.
|
|
|
- Explorer drill-down.
|
|
- Explorer drill-down.
|
|
|
- Search scopes (admin-like) + Search restrictions (branch).
|
|
- Search scopes (admin-like) + Search restrictions (branch).
|
|
|
- Open PDFs.
|
|
- Open PDFs.
|
|
|
|
|
+- User management UI (superadmin/dev): list/create/update/delete.
|
|
|
|
|
|
|
|
-### 15.2 Server
|
|
|
|
|
|
|
+### 16.2 Server
|
|
|
|
|
|
|
|
- Repeat the local checks on the real server.
|
|
- Repeat the local checks on the real server.
|
|
|
- Validate RBAC behavior:
|
|
- Validate RBAC behavior:
|
|
|
- branch user → forbidden on foreign branches
|
|
- branch user → forbidden on foreign branches
|
|
|
- admin-like → notfound on non-existent branches
|
|
- admin-like → notfound on non-existent branches
|
|
|
|
|
+ - admin/branch → forbidden on `/admin/users`
|
|
|
|
|
|
|
|
---
|
|
---
|
|
|
|
|
|
|
|
-## 16. Planned follow-ups
|
|
|
|
|
|
|
+## 17. Planned follow-ups
|
|
|
|
|
+
|
|
|
|
|
+- User management UX hardening (separate ticket):
|
|
|
|
|
+ - delete with explicit username confirmation
|
|
|
|
|
+ - branch user creation UX (fixed `NL` prefix + numeric-only input)
|
|
|
|
|
+ - optional branch existence check / warning when creating branch users
|
|
|
|
|
|
|
|
-- User management UI + APIs (RHL-012):
|
|
|
|
|
- - Guard endpoints using `requireUserManagement(session)` (backend).
|
|
|
|
|
- - Gate UI screens using `canManageUsers(role)` (frontend).
|
|
|
|
|
|
|
+- `mustChangePassword` enforcement (separate ticket):
|
|
|
|
|
+ - redirect/gate until password is changed
|