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>
9.6 KiB
9.6 KiB
P03 · Audit & Notifications (AK-P3 → D-P3)
Interim-UI-Referenz (AD-28). Beide Domänen sind AK-P3-Interim-Screens, rein aus
~/uikomponiert, VM als Prop. Layout = Davids freie Hand — Listen nennen nur Elemente/Daten/Aktionen/States. Keine der fünf Dateien importiert@subframe/core/Icons; alle Affordances aus~/ui-Primitives.
Audit
AuditListPage · Audit-Viewer (A2 + Drawer)
- Interim-Screen:
apps/web/app/components/screens/audit/AuditListPage.tsx - Route(n):
/admin/audit(routes/admin/audit.tsx) — Admin-Host, nichtapp.$tenant. Permission-Gateadmin.auditTrails.view. - Daten (VM):
AuditListVM(Rows/Filter überAuditListFilterState,AuditListRow) —packages/view-models/src/audit/audit-list.vm.ts - Benötigte UI-Elemente (KEIN Layout): Alert · Button · Drawer · EmptyState · Select (+ Select.Item) · Table (HeaderRow/HeaderCell/Row/Cell) · Tag_Label · TextInput (+ TextInput.Input) · DateField (lokal
../tasks/DateField). Inhaltselemente: Header (Titel + Subtitle + Export-CTA nur beicanExport), Filter-Bar (from/to Datum, Actor-Type-Select, Outcome-Select, Action-Text, TargetType-Text, Apply-Button), Tabelle (Zeit/Actor+Kind-Tag/Action monospace/Subjekt/Outcome/Summary + Detail-Button beihasDetail), Server-Pagination (pageInfo + prev/next), Detail-Drawer (Feld-für-Feld-Diff-Tabelle mit „masked"→Tag „Wert geändert", Metadata<pre>, leer→Alert). Icons: keine. - Interaktionen (Actions):
onApply(query: AuditListQuery)—AuditListQuery = AuditListFilterState & { page: number }; getriggert von Filter-Submit, Select-onValueChange, prev/next. Detail-Drawer öffnet rein lokal (useState openRowId), kein Action-Callback. - States: Loading =
vm.status !== "ready"→ leerer Marker-Div · Empty =rows.length === 0→ EmptyState (emptyHeadlineKey/emptyBodyKey) · Drawer-Empty = kein Diff/Metadata → Alert · Permission-Denied = Route-Level 404 (verifyUserHasPermission), kein In-Component-403. - Davids Delta (offen):
- Überschriebene/geänderte Spec-Punkte: Quick-Filter (Klick auf Actor/Subject/Action) und „Verlauf dieses Objekts"/„Ähnliche Einträge" aus D-P3-Zeile sind im Interim NICHT gebaut — nur Formular-Filter + Diff-Drawer.
- Neue UI/UX-Entscheidungen: visuelle Unterscheidung der Actor-Kinds (User/Automation/MCP/Agent/Admin) — interim nur neutrales Tag_Label.
- Subframe-Screen-Link(s):
- Offene Fragen an Dev: Sollen Quick-Filter denselben
onApplynutzen (Patch je Feld)?
AuditExportPage · Audit-Export-Jobs (A2)
- Interim-Screen:
apps/web/app/components/screens/audit/AuditExportPage.tsx - Route(n):
/admin/audit-export(routes/admin/audit-export.tsx) — Admin-Host. (Tenant-Varianteapp.$tenant/settings/audit-export.tsx=/app/:tenant/settings/audit-exportrendert eigenes Inline-UI, NICHT diesen Interim-Screen.) - Daten (VM):
AuditExportVM(+AuditExportResultVMalsresult-Prop) —packages/view-models/src/audit/audit-export.vm.ts - Benötigte UI-Elemente (KEIN Layout): Alert · Button · Select (+ Select.Item, Helper
SelectWithAny) · TextInput (+ TextInput.Input) · DateField (lokal../tasks/DateField). Inhaltselemente: Header (Titel + Beschreibung mitmaxRows), ein Formular mit drei Submit-Pfaden (GET csv / GET pdf / POST storage-export), Filterfelder (from/to, tenantId optional, regulatoryScope/actorType/outcome je Select-mit-„Any", purpose Pflicht-Textfeld, format Select), Ergebnis-Panel (Erfolg/Warn-Alert mit Download-Link + Integritäts-Warnung, oder Error-Alert). Icons: keine. - Interaktionen (Actions): KEIN
…Actions-Typ — reine HTML-Form-Submits gegen die Route (GET streamt CSV/PDF, POST läuft Storage-Export). Einzige Prop nebenvmistresult(Aktions-Ergebnis, null = noch nichts abgeschickt). - States: Loading =
vm.status !== "ready"→ leerer Marker-Div · Ergebnis:result.ok===false→ Error-Alert (errorKey);result.ok→ Success/Warning-Alert (Row-Count, Ablauftage, Download-Link, ggf. Integritäts-Warnung);result===null→ kein Panel · Kein Empty-State · Permission-Denied = Route-Level 404. - Davids Delta (offen):
- Überschriebene/geänderte Spec-Punkte: D-P3 sieht Export-Job-Liste +
/new+/:id(A2) vor — Interim ist ein Single-Formular ohne Job-Liste/Detail-Route. - Neue UI/UX-Entscheidungen: Zweck-Pflichtfeld (
purpose) Prominenz; Format-Auswahl CSV/PDF vs. Spec CSV/NDJSON. - Subframe-Screen-Link(s):
- Offene Fragen an Dev: Job-Liste/
:id-Status als eigene D-P3-Screens nachziehen oder Single-Form-Ansatz beibehalten?
- Überschriebene/geänderte Spec-Punkte: D-P3 sieht Export-Job-Liste +
Notifications
NotificationCenterPage · Notification-Center (A2 + Drawer)
- Interim-Screen:
apps/web/app/components/screens/notifications/NotificationCenterPage.tsx - Route(n):
/app/:tenant/notifications(routes/app.$tenant/notifications.tsx) — Route hostet SSE-Subscription (useNotificationsStream). - Daten (VM):
NotificationCenterVM(Items überNotificationCenterItemVM) —packages/view-models/src/notifications/notification-center.vm.ts - Benötigte UI-Elemente (KEIN Layout): Alert · BadgeFeedback · Button · EmptyState · Tabs (+ Tabs.Item). Inhaltselemente: Header (Titel + Diagnostics-Subtitle + sr-only Live-Region für
connectionStatusKey), Tabs Alle/Ungelesen mit Counts, Bulk-Clear-Button (nur beiunreadCount>0), Notification-Cards (Message als Deeplink-Link oder Text, Kategorie·Channel·Zeit-Metazeile, Status-Badge farbcodiert READ/FAILED/PENDING, Bounce-Alert beibounceKeymitlastErrorRedacted, Mark-Read-Button bei ungelesen). Icons: keine. - Interaktionen (Actions):
onMarkRead(deliveryId: string)·onMarkAllRead(). Tab-Umschaltung Alle/Ungelesen ist lokal (useState). - States: Loading =
vm.status !== "ready"→ leerer Marker-Div · Empty =totalCount===0→ EmptyState (emptyHeadlineKey/emptyBodyKey) · Unread-Empty = gefilterte Liste leer → EmptyState (unreadEmptyKey) · Permission-Denied = Route-Level (Auth-Middleware), kein In-Component-403. - Davids Delta (offen):
- Überschriebene/geänderte Spec-Punkte: D-P3 nennt Prioritäts-Marker + Mark-unread — Interim hat nur Mark-read (kein Priority-Marker, kein Unread-Zurücksetzen).
- Neue UI/UX-Entscheidungen: Bounce-Klartext-Darstellung („Emails an dich kommen aktuell nicht an") als Error-Alert je Card.
- Subframe-Screen-Link(s):
- Offene Fragen an Dev: Priority-Marker-Datenfeld im VM ergänzen?
NotificationsDrawer · Notification-Center Topbar-Drawer (A2 + Drawer)
- Interim-Screen:
apps/web/app/components/screens/notifications/NotificationsDrawer.tsx - Route(n): n/a — Shell-Level-Komponente (globaler Drawer, gehostet von
apps/web/app/components/layouts/NavBar.tsx; NavBar besitzt SSE-Subscription + Open-State). - Daten (VM):
NotificationCenterItemVM(kein eigener VM; Items als Prop, max 10) —packages/view-models/src/notifications/notification-center.vm.ts - Benötigte UI-Elemente (KEIN Layout): BadgeFeedback · Button · Drawer (+ Drawer.Content) · EmptyState. Inhaltselemente: Header (Titel + Close-Button), Item-Liste (max 10; Message als Deeplink oder Text, ungelesen fett, Zeitstempel, „Ungelesen"-Badge bei nicht gelesen), „Alle anzeigen"-Link (
allHref). Icons: keine. - Interaktionen (Actions): KEIN
…Actions-Typ — Propsopen,items,allHref,onClose(). Deeplink-Klicks folgen validiertendeeplinkHref; „Alle anzeigen" navigiert zuallHref. - States: Empty =
visibleItems.length===0→ EmptyState (drawer.empty+emptyHelper) · kein eigenes Loading/Permission-Denied (Shell steuert Sichtbarkeit). - Davids Delta (offen):
- Überschriebene/geänderte Spec-Punkte: kein Mark-read/Bulk-Clear im Drawer (nur „Alle anzeigen" → Center).
- Neue UI/UX-Entscheidungen: Verhältnis Bell-Slot (D-D0a) ↔ Drawer-Öffnung; 10-Item-Cap.
- Subframe-Screen-Link(s):
- Offene Fragen an Dev: Soll der Drawer Inline-Mark-read bekommen oder bewusst read-only bleiben?
NotificationSettingsPage · Notification-Settings (A6)
- Interim-Screen:
apps/web/app/components/screens/notifications/NotificationSettingsPage.tsx - Route(n):
/app/:tenant/settings/notifications(routes/app.$tenant/settings/notifications.tsx) — Actions fetcher-backed. - Daten (VM):
NotificationSettingsVM(Channel-TypNotificationSettingChannel) —packages/view-models/src/notifications/notification-settings.vm.ts - Benötigte UI-Elemente (KEIN Layout): Alert · Switch (+ lokaler
ChannelToggle-Wrapper). Inhaltselemente: Header (Heading + Description), Save-State-Alert, Master-Karte „alle Emails aus" (Switch), pro Modul-Gruppe eine Karte mit Modul-Label + je Kategorie In-App/Email-Toggle. Icons: keine. - Interaktionen (Actions):
onTogglePreference({ category, channel, enabled })·onSetEmailMaster(disableAllEmails: boolean)(Master-Switch schreibt alle Kategorien). Zusätzliche PropsaveState: { ok; errorText? } | null. - States: Loading =
vm.status !== "ready"→ leerer Marker-Div · Save =saveState.ok→ Success-Alert / sonst Error-Alert (errorText) ·saveState===null→ nichts · kein Empty-State (Registry liefert immer Gruppen) · Permission-Denied = Route-Level. - Davids Delta (offen):
- Überschriebene/geänderte Spec-Punkte: D-P3 nennt Priority-Selektor je Event-Typ — Interim hat nur In-App/Email-Toggles, keinen Priority-Selektor.
- Neue UI/UX-Entscheidungen: Master-Toggle-Klartext „betrifft auch zukünftige Event-Typen".
- Subframe-Screen-Link(s):
- Offene Fragen an Dev: Priority pro Kategorie im VM/Registry ergänzen?