Files
AkeshanandClaude Opus 4.8 d8b6772148 Interim-UI-Handover: 55 Vorschau-Screens fuer David (AD-28)
Uebergabe der Dev-Interim-Screens aus HiveGrid-Cloud an den Wireframes-Vault.
INDEX + 7 Domaenen-Seiten (CRM, Leads, HR, Files/Tasks, Audit/Notifications,
Integrations, Auth/RBAC) mit je Screen: D-*-Ziel, Archetyp, Route, VM,
benoetigte ~/ui-Elemente, Actions, States. Layout bleibt Davids freie Hand.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 17:35:12 +02:00

54 lines
6.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# P02 · Auth & RBAC (R-P2a/b → D-P2)
> ℹ️ David-Delta liegt vor (`Tickets/Fertige Tickets/D-P2 Auth Wireframes.md`) — diese Seite dient dem
> Konsistenz-Abgleich, **kein neuer Design-Request**. Interim-UI-Referenz (AD-28), `~/ui`-komponiert, VM als Prop.
## Auth
### CreateWorkspacePage · D-P2 „Create-workspace (ohne Tenant)" · A3 Formular/Auth-Shell (kein A-Code im Header, inferiert)
- **Interim-Screen:** `apps/web/app/components/screens/auth/CreateWorkspacePage.tsx`
- **Route(n):** `/new-account` (`routes/new-account.tsx`) — nicht unter `app.$tenant/` (Pre-Tenant-Screen)
- **Daten (VM):** keine VM — reine Props `{ csrf, error?, backHref }` (route-injiziert; server-driven `/new-account`-Action erstellt den Tenant)
- **Benötigte UI-Elemente (KEIN Layout):** `~/ui`: Alert, Button, LinkButton, TextInput · Shell: `~/components/auth/AuthShell` (nicht `~/ui`) · Icons: FeatherArrowLeft
- **Interaktionen (Actions):** keine `…Actions` — natives `<form method="post">` postet `name` + `csrf` (+ vestigiales `action=create`); Back-Link → `backHref`
- **States:** Error-Alert (nur idle-gated, `error`-Prop) · kein Empty/Loading · Permission-Denied n/a (Login-gated im Loader)
- **Davids Delta:** ✅ vorhanden (D-P2) — nur Abgleich
## Users / RBAC
### MembersPage · D-P2 „WF-P2 Admin RBAC" S01 Mitarbeiterliste (+ D01/M03/V01) · A1 Liste/Tabelle (kein A-Code im Header, inferiert)
- **Interim-Screen:** `apps/web/app/components/screens/users/MembersPage.tsx`
- **Route(n):** `/app/:tenant/settings/members` (`routes/app.$tenant/settings/members.tsx`)
- **Daten (VM):** `MembersListVM` — `packages/view-models/src/users/members-list.vm.ts` (+ Helfer `filterMembersRows`, `EMPTY_MEMBERS_FILTER`, Typen `MembersListRow`/`MembersListFilterState`/`MemberStatus`)
- **Benötigte UI-Elemente (KEIN Layout):** `~/ui`: Avatar, BadgeFeedback, Button, Checkbox, Dialog, DropdownMenu, EmptyState, IconButton, SearchInput, Select, Table, Tabs · Icons: FeatherChevronDown, FeatherMoreHorizontal, FeatherPlus, FeatherTrash, FeatherUserCheck, FeatherUserX (+ `SubframeCore.DropdownMenu`)
- **Interaktionen (Actions):** `MembersActions` — onToggleRole({userId, roleId, add}), onDeactivate({userId}), onReactivate({userId}), onDeleteInvitation({invitationId}), onInvite()
- **States:** Empty (`EmptyState`, `emptyHeadlineKey`/`emptyBodyKey` wenn keine Rows/Invites) · No-matches (`EmptyState`, `noMatchesKey`) · Loading (`vm.status !== "ready"` → leeres Gerüst) · M03 Deaktivieren-Confirm-Dialog · V01 Last-Admin-Blocker-Dialog · Permission-Denied → 404 im Loader (`verifyUserHasPermission`)
- **Davids Delta:** ✅ vorhanden (D-P2) — nur Abgleich
### RolesPage · D-P2 „WF-P2 Admin RBAC" S02 Rollen & Berechtigungen (+ M04A/M04B/M02/D03) · A1 Liste/Tabelle + Editor-Dialog (kein A-Code im Header, inferiert)
- **Interim-Screen:** `apps/web/app/components/screens/users/RolesPage.tsx`
- **Route(n):** `/app/:tenant/settings/roles-and-permissions/roles` (`routes/app.$tenant/settings/roles-and-permissions/roles.tsx`)
- **Daten (VM):** `RolesListVM` — `packages/view-models/src/users/roles-list.vm.ts` (+ Editor-VM `buildRoleEditorVM`/`filterRoleEditorSections`/`togglePermission` + Typ `RoleEditorInputPermission` aus `packages/view-models/src/users/role-editor.vm.ts`; Helfer `filterRolesRows`, `EMPTY_ROLES_FILTER`, Typen `RolesListRow`/`RolesListFilterState`/`RoleTypeKey`)
- **Benötigte UI-Elemente (KEIN Layout):** `~/ui`: Alert, Button, Dialog, DropdownMenu, EmptyState, IconButton, SearchInput, Select, Switch, Table, Tabs, TextArea, TextInput · Icons: FeatherCopy, FeatherEdit2, FeatherMoreHorizontal, FeatherPlus, FeatherTrash (+ `SubframeCore.DropdownMenu`)
- **Interaktionen (Actions):** `RolesActions` — onCreate({name, description, permissionNames}), onUpdate(roleId, {name, description, permissionNames}), onDelete(roleId)
- **States:** Empty (`EmptyState`, `emptyHeadlineKey`/`emptyBodyKey` wenn keine Rollen) · No-matches (`EmptyState variant="no-results"`, `noMatchesKey`) · Loading (`vm.status !== "ready"` → leeres Gerüst) · M02-Editor No-matches (`EmptyState`) · D03 Delete-Blocker (`deleteBlockedInUse`) · Permission-Denied → 404 im Loader (`requireWorkspaceRolesBuilderAccess`)
- **Davids Delta:** ✅ vorhanden (D-P2) — nur Abgleich
### InviteMemberForm · D-P2 „WF-P2 Admin RBAC" M01 „Mitarbeiter einladen" · A4 Dialog-Formular (kein A-Code im Header, inferiert)
- **Interim-Screen:** `apps/web/app/components/screens/users/InviteMemberForm.tsx`
- **Route(n):** n/a — Sub-Komponente von `MembersSettingsRoute` (rendert im Outlet-Dialog; postet an `routes/app.$tenant/settings/members/new.tsx`)
- **Daten (VM):** keine VM — nutzt `NewMemberActionData` aus `~/routes/app.$tenant/settings/members/new` (via `useActionData`) + `useRootData` (csrf)
- **Benötigte UI-Elemente (KEIN Layout):** `~/ui`: Button, Checkbox, TextInput · Icons: keine
- **Interaktionen (Actions):** keine `…Actions` — `<Form method="post">` an `members/new` (Felder `email`, `first-name`, `last-name`, `send-invitation-email`, `csrf`); Prop-Callback `onClose()`
- **States:** Error-Toast (`actionData.error`) · Loading (`navigation.state === "submitting"` → Submit-Button loading) · kein Empty · Permission-Denied via Parent-Route
- **Davids Delta:** ✅ vorhanden (D-P2) — nur Abgleich
### GroupMembersDialog · D-P2 „WF-P2 Admin RBAC" Gruppen-Bulk (RBAC V2, offener design-nachzug) · A4 Dialog (kein A-Code im Header, inferiert)
- **Interim-Screen:** `apps/web/app/components/screens/users/GroupMembersDialog.tsx`
- **Route(n):** n/a — Sub-Komponente von `GroupsRoute` (`routes/app.$tenant/settings/groups.tsx`, URL `/app/:tenant/settings/groups`; postet Bulk an `settings/groups/:id`)
- **Daten (VM):** `GroupsDetailVM` — `packages/view-models/src/users/groups-detail.vm.ts` (+ Helfer `filterGroupMemberRows`, Typ `GroupMemberRow`)
- **Benötigte UI-Elemente (KEIN Layout):** `~/ui`: Avatar, Button, Checkbox, Dialog, EmptyState, SearchInput · Icons: keine
- **Interaktionen (Actions):** `GroupMembersActions` — onAdd(userIds: string[]), onRemove(userIds: string[]); Prop-Callback `onClose()`
- **States:** Loading (`vm.status !== "ready"` → `null`) · Empty pro Pick-Liste (`EmptyState variant="no-results"`, `emptyMembersKey`/`emptyCandidatesKey`) · Permission-Gate: Add/Remove-Buttons nur bei `data.canManage`
- **Davids Delta:** ✅ vorhanden (D-P2) — nur Abgleich