|
|
@@ -1,4 +1,4 @@
|
|
|
-# Frontend UI: App Shell, Routing, Auth/RBAC, Explorer, Search, Date Range Filter, Navigation Polish, Profile Password Change, User Management, Role Refinement, and Must-Change-Password Gate (RHL-019 / RHL-020 / RHL-021 / RHL-022 / RHL-023 / RHL-024 / RHL-025 / RHL-037 / RHL-032 / RHL-009 / RHL-012 / RHL-041 / RHL-044)
|
|
|
+# Frontend UI: App Shell, Routing, Auth/RBAC, Explorer, Search, Date Range Filter, Navigation Polish, Profile Password Change, User Management, Role Refinement, Must-Change-Password Gate, and User Management UX Hardening (RHL-019 / RHL-020 / RHL-021 / RHL-022 / RHL-023 / RHL-024 / RHL-025 / RHL-037 / RHL-032 / RHL-009 / RHL-012 / RHL-041 / RHL-044 / RHL-043)
|
|
|
|
|
|
This document describes the **frontend routing scaffold**, the **application shell layout**, and the core UI modules for the RHL Lieferscheine app.
|
|
|
|
|
|
@@ -17,6 +17,13 @@ Timeline:
|
|
|
- **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.
|
|
|
- **RHL-044**: Must-change-password enforcement (central protected-route gate, `/profile` redirect, and post-change resume flow).
|
|
|
+- **RHL-043**: User management UX hardening + layout cleanup:
|
|
|
+ - safer delete flow (typed username confirmation),
|
|
|
+ - branch input hardening (`NL` + numeric draft) + branch existence validation with fail-open note,
|
|
|
+ - loaded-count + users sorting toolbar,
|
|
|
+ - temporary-password controls (reset/show/copy + tooltips) in table and edit dialog,
|
|
|
+ - sticky icon-only action column polish,
|
|
|
+ - AppShell cleanup (remove sidebar placeholder, desktop width to `75%`).
|
|
|
|
|
|
> **Language policy**
|
|
|
>
|
|
|
@@ -28,22 +35,27 @@ Timeline:
|
|
|
|
|
|
## 1. Scope
|
|
|
|
|
|
-### 1.1 Implemented (as of RHL-012 + RHL-041 + RHL-037 + RHL-025 + RHL-032 + RHL-009 + RHL-044)
|
|
|
+### 1.1 Implemented (as of RHL-012 + RHL-041 + RHL-037 + RHL-025 + RHL-032 + RHL-009 + RHL-044 + RHL-043)
|
|
|
|
|
|
- **Public** `/login` route with a functional login form (shadcn/ui primitives).
|
|
|
|
|
|
- **Protected** application shell for all authenticated routes:
|
|
|
- Top navigation (branding, quick navigation, actions)
|
|
|
- - Sidebar placeholder area
|
|
|
+ - Centered main content container
|
|
|
- Main content area
|
|
|
|
|
|
+ Width policy:
|
|
|
+
|
|
|
+ - mobile/tablet: full width
|
|
|
+ - desktop (`lg+`): centered `w-3/4` content for a wider but bounded workspace
|
|
|
+
|
|
|
- **Session guard** for protected routes:
|
|
|
- Session identity is checked via `GET /api/auth/me`.
|
|
|
- When unauthenticated: redirect to `/login?reason=expired&next=<original-url>`.
|
|
|
|
|
|
- **In-shell auth gating (UX improvement)**:
|
|
|
- Auth loading/error/redirect states render **inside** the AppShell main content.
|
|
|
- - AppShell (TopNav + sidebar) remains stable; no “blank spinner screens”.
|
|
|
+ - AppShell (TopNav + main content frame) remains stable; no “blank spinner screens”.
|
|
|
|
|
|
- **Logout**:
|
|
|
- Logout action calls `GET /api/auth/logout` and redirects to `/login?reason=logged-out`.
|
|
|
@@ -84,18 +96,24 @@ Timeline:
|
|
|
- `isAdminLike(role)` → `admin | superadmin | dev`
|
|
|
- `canManageUsers(role)` → `superadmin | dev`
|
|
|
|
|
|
-- **User management UI (RHL-012)**:
|
|
|
+- **User management UI (RHL-012 + RHL-043 hardening)**:
|
|
|
- Route: `/admin/users` (protected)
|
|
|
- Permission gating:
|
|
|
- allowed: `superadmin`, `dev`
|
|
|
- forbidden: `admin`, `branch`
|
|
|
|
|
|
- - Features (v1):
|
|
|
+ - Features:
|
|
|
- list users with filters (username/email search, role, branchId)
|
|
|
+ - loaded-count indicator (`X Benutzer geladen`) in the users toolbar
|
|
|
+ - sort toolbar (`Standard`, `Rolle (Rechte)`, `Niederlassung (NL)`)
|
|
|
- create user dialog (initial password + must-change-password flag on create)
|
|
|
+ - create/edit branch input hardening (`NL` prefix + numeric input draft)
|
|
|
+ - create/edit branch existence checks against `/api/branches` with fail-open note
|
|
|
- update user (role/branchId consistency enforced)
|
|
|
- - delete user
|
|
|
- - cursor-based pagination (“Mehr laden”)
|
|
|
+ - delete user with typed-username confirmation gate
|
|
|
+ - temporary password controls (reset, reveal/hide, copy) in table + edit dialog
|
|
|
+ - sticky right action column with icon-only actions (edit/delete)
|
|
|
+ - cursor-based pagination (“Mehr laden”), consistent with selected sort mode
|
|
|
|
|
|
- **UI RBAC (branch-level)**:
|
|
|
- `BranchGuard` prevents branch users from accessing other branches’ URLs.
|
|
|
@@ -174,10 +192,9 @@ Timeline:
|
|
|
- add a dedicated “Herunterladen” UI action (download variant)
|
|
|
- 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
|
|
|
+- Optional user management enhancements (not implemented in RHL-043):
|
|
|
+ - additional branch list filtering in branch pickers (create/edit)
|
|
|
+ - one-click “copy username” helper
|
|
|
|
|
|
---
|
|
|
|
|
|
@@ -270,23 +287,18 @@ File: `components/app-shell/AppShell.jsx`
|
|
|
AppShell is the stable frame for all protected pages:
|
|
|
|
|
|
- TopNav is always visible.
|
|
|
-- The sidebar is currently a placeholder (reserved for future navigation/filter UI).
|
|
|
-- Route pages render inside the main content area.
|
|
|
+- Route pages render inside the main content area (no sidebar rail).
|
|
|
|
|
|
-#### 4.1.1 Width policy and sidebar docking (2xl+)
|
|
|
-
|
|
|
-On very wide screens the UI should remain readable.
|
|
|
+#### 4.1.1 Width policy
|
|
|
|
|
|
Current strategy (implemented in `AppShell.jsx` + `TopNav.jsx`):
|
|
|
|
|
|
-- Use a centered content column (~45% of the viewport at `2xl+`).
|
|
|
-- Keep the Explorer/Search content inside that centered column.
|
|
|
-- Render the sidebar in the left gutter and align it to the right edge so it “docks” to the centered content **without consuming the centered width**.
|
|
|
-
|
|
|
-Below `2xl`:
|
|
|
+- keep content full-width on smaller screens,
|
|
|
+- switch to a centered `lg:w-3/4` container on desktop for both:
|
|
|
+ - TopNav inner row,
|
|
|
+ - protected page content area.
|
|
|
|
|
|
-- Use full width for usability.
|
|
|
-- Hide the sidebar placeholder to avoid shrinking the main content area.
|
|
|
+This keeps header and content visually aligned and avoids horizontal “jump” between navigation and page body.
|
|
|
|
|
|
### 4.2 TopNav structure (RHL-032)
|
|
|
|
|
|
@@ -667,7 +679,7 @@ The project uses Sonner (shadcn/ui integration) for toast notifications.
|
|
|
|
|
|
---
|
|
|
|
|
|
-## 11. User management UI (RHL-012)
|
|
|
+## 11. User management UI (RHL-012 + RHL-043)
|
|
|
|
|
|
### 11.1 Route
|
|
|
|
|
|
@@ -685,8 +697,13 @@ Files:
|
|
|
|
|
|
- `components/admin/users/AdminUsersPage.jsx` (gating)
|
|
|
- `components/admin/users/AdminUsersClient.jsx` (list + filters + actions)
|
|
|
+- `components/admin/users/AdminUsersTableToolbar.jsx` (loaded count + sort dropdown)
|
|
|
- `components/admin/users/UsersTable.jsx` (table)
|
|
|
+- `components/admin/users/UserTemporaryPasswordField.jsx` (temporary password controls)
|
|
|
+- `components/admin/users/DeleteUserDialog.jsx` (delete safety dialog)
|
|
|
+- `components/admin/users/BranchNumberInput.jsx` (fixed `NL` prefix + numeric input)
|
|
|
- `components/admin/users/CreateUserDialog.jsx` + `components/admin/users/create-user/*` (create flow)
|
|
|
+- `components/admin/users/EditUserDialog.jsx` + `components/admin/users/edit-user/*` (edit flow)
|
|
|
|
|
|
The UI uses the API client wrappers from `lib/frontend/apiClient.js`:
|
|
|
|
|
|
@@ -694,6 +711,63 @@ The UI uses the API client wrappers from `lib/frontend/apiClient.js`:
|
|
|
- `adminCreateUser`
|
|
|
- `adminUpdateUser`
|
|
|
- `adminDeleteUser`
|
|
|
+- `adminResetUserPassword`
|
|
|
+
|
|
|
+### 11.4 UX hardening rules (RHL-043)
|
|
|
+
|
|
|
+- Delete flow requires explicit typed confirmation:
|
|
|
+ - dialog shows the target user details,
|
|
|
+ - user must type the username,
|
|
|
+ - delete button stays disabled until the normalized value matches.
|
|
|
+
|
|
|
+- Branch-role input hardening (`role=branch`) in create and edit:
|
|
|
+ - fixed prefix `NL`,
|
|
|
+ - numeric input draft for the branch number,
|
|
|
+ - normalization output examples:
|
|
|
+ - `1` -> `NL01`
|
|
|
+ - `32` -> `NL32`
|
|
|
+ - `200` -> `NL200`
|
|
|
+ - typing stability: drafts like `01` remain visible while typing.
|
|
|
+
|
|
|
+- Branch existence validation:
|
|
|
+ - if `/api/branches` is available and selected branch does not exist:
|
|
|
+ - inline error is shown,
|
|
|
+ - submit is blocked.
|
|
|
+ - if `/api/branches` cannot be loaded:
|
|
|
+ - submit is not hard-blocked (fail-open),
|
|
|
+ - a small informational note is shown.
|
|
|
+
|
|
|
+### 11.5 Table UX details
|
|
|
+
|
|
|
+- Users toolbar (above table):
|
|
|
+ - loaded count badge (`X Benutzer geladen`)
|
|
|
+ - sorting dropdown:
|
|
|
+ - `Standard`
|
|
|
+ - `Rolle (Rechte)`
|
|
|
+ - `Niederlassung (NL)`
|
|
|
+
|
|
|
+- Table layout:
|
|
|
+ - fixed/sticky right `Aktion` column for edit/delete actions,
|
|
|
+ - icon-only edit/delete actions to reduce horizontal space.
|
|
|
+
|
|
|
+- Temporary password column:
|
|
|
+ - masked display by default (`••••••`),
|
|
|
+ - controls:
|
|
|
+ - reset temporary password,
|
|
|
+ - reveal/hide,
|
|
|
+ - copy to clipboard,
|
|
|
+ - copy feedback:
|
|
|
+ - success checkmark state after copy,
|
|
|
+ - fallback copy path for browsers/environments where `navigator.clipboard` is not usable.
|
|
|
+
|
|
|
+- Tooltips:
|
|
|
+ - temporary-password control buttons use tooltips for discoverability and consistent icon-only UX.
|
|
|
+
|
|
|
+### 11.6 Sorting and pagination behavior
|
|
|
+
|
|
|
+- Sorting is applied server-side (`/api/admin/users?sort=...`) and remains stable across `Mehr laden`.
|
|
|
+- Cursor payload carries sort context to prevent cross-mode cursor reuse.
|
|
|
+- Frontend query state includes `sort` so changing sort resets the list cleanly.
|
|
|
|
|
|
---
|
|
|
|
|
|
@@ -767,7 +841,13 @@ npm run build
|
|
|
- Explorer drill-down.
|
|
|
- Search scopes (admin-like) + Search restrictions (branch).
|
|
|
- Open PDFs.
|
|
|
-- User management UI (superadmin/dev): list/create/update/delete.
|
|
|
+- User management UI (superadmin/dev):
|
|
|
+ - list/create/update/delete
|
|
|
+ - delete typed confirmation
|
|
|
+ - branch input (`NL` + number) and branch existence warning/blocking
|
|
|
+ - temporary password reset/reveal/copy controls
|
|
|
+ - sorting (`Standard`, `Rolle (Rechte)`, `Niederlassung (NL)`)
|
|
|
+ - sticky action column behavior on horizontal overflow
|
|
|
|
|
|
### 16.2 Server
|
|
|
|
|
|
@@ -785,7 +865,6 @@ npm run build
|
|
|
|
|
|
## 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
|
|
|
+- Optional user-management polish:
|
|
|
+ - additional branch-list filtering in the create/edit branch picker UX
|
|
|
+ - optional one-click username copy helper
|