Die Seiten holten ihre Zahlen selbst aus einem globalen Store. HiveGrid Cloud
verlangt reine Screens nach dem Muster <XPage vm={} actions={} /> — jede Seite
hätte beim Einbau auseinandergenommen werden müssen.
Neue Schichtung:
view-models/<seite>.vm.ts baue<Seite>VM(daten, filter) → VMState<…>
reine Funktion, kein React, kein Store
pages/<Seite>.tsx ({ vm, optionen }) → JSX wird portiert
routes/<Seite>Route.tsx Store + Builder + Seite wird ersetzt
view-models/index.ts spiegelt VMState wortgleich aus @hivegrid/view-models;
beim Einbau ist es ein Import-Wechsel. Der Loader ruft denselben Builder mit
echten Daten, die Seiten bleiben unberührt.
Dabei abgefallen: die fünf Seitenzustände (idle · loading · ready · empty ·
error) über SeitenZustand — bisher lief der Prototyp nur im Zustand "Daten da",
in der Cloud sind alle fünf DoD-Pflicht. Die Filterleiste bekommt ihre
Auswahllisten jetzt als Prop (in der Software die Facetten aus dem Loader)
statt sie selbst aus dem Datensatz zu ziehen.
Store- und Rohdatenzugriff gibt es damit ausschließlich in routes/. Alle sechs
Seiten rendern pixelgleich; typecheck, lint und build sind grün.
Nicht geändert: Next.js bleibt. Im gesamten Projekt gibt es vier
Next-spezifische Importe, alle in AppShell und app/layout — beide Dateien
entfallen beim Einbau ohnehin, weil die Cloud Shell und Root-Layout mitbringt.
Ein Framework-Wechsel wäre Aufwand ohne Ertrag.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QPeZNwSeU7qG3RRCwaxEZX
9.9 KiB
Leitplanken aus HiveGrid Cloud
Welche Bereiche der Zielanwendung bereits Davids finale Subframe-Screens tragen und welche noch auf Interim-UI laufen — und was daraus für dieses Dashboard verbindlich ist.
Warum die Unterscheidung zählt: Ein nachgezogener Screen ist eine Design-Entscheidung, an der man sich ausrichten kann. Eine Interim-UI ist eine Notlösung des Devs — sie kopieren hieße, einen Platzhalter zum Standard zu erklären.
Stand der Auswertung: 2026-08-29 gegen den lokalen Repo-Stand.
1. Woran man es im Code erkennt
Der Repo pflegt dafür bewusste Marker. In absteigender Verlässlichkeit:
| Muster | Bedeutung |
|---|---|
Interim-UI (AD-28) im Kopfkommentar |
Optik ist ausdrücklich vorläufig |
design-nachzug |
offener Punkt — steht auch in sonst fertigen Screens für einzelne Reste |
Kopfkommentar mit Subframe-Screen-ID (WF-P8 S03, S02/S02L/S03/S05), Page-UUID oder „gegen Davids Export vom …" |
nachgezogen, Optik ist abgestimmt |
@subframe/sync-disable in apps/web/app/ui/** |
lokal geänderte Komponente, die der Sync nicht überschreiben darf |
Ein typischer Interim-Kopf (projects/PipelineKanbanPage.tsx):
// R-P8b (P8 configurable Kanban) Interim-UI (AD-28) — pipeline board screen// (D-KANBAN), composed from ~/ui …
Ein typischer nachgezogener Kopf (projects/ProjektListPage.tsx):
// WF-P8 S03 "Projekt-Liste" — rebuilt against Davids Subframe export of// 2026-07-28 (page 5c5bdb0a-995e-4c22-aa8b-e48333c60297) …
Autoritativ ist aber die Liste, nicht der Kommentar:
.planning/SUBFRAME-FLOW-INVENTAR.md trackt jeden Subframe-Flow mit Seitenzahl,
Owner und Stand. Der dortige Hinweis ist wichtig: Der Subframe-Sync pflegt nur
Components, Layouts und Theme — Pages werden nie automatisch integriert,
jeder Screen wird einzeln hinter der Loader/Action-Grenze verdrahtet.
Grenze der Methode: Ein fehlender Marker sagt nichts. Von 214
*Page.tsx-Dateien tragen 92 einen Interim-Marker, 36 einen Subframe-Bezug und
86 gar keinen — überwiegend Plattform-Admin (31) und Integrationen (13),
also interne Flächen mit niedrigem Politur-Druck.
2. Die Abgrenzung
Nachgezogen — als Leitplanke brauchbar
| Bereich | Stand laut Inventar | Im Code |
|---|---|---|
| Team-Chat | 🟢 24 von 24 Screens integriert (Handoff 2026-08-08) | screens/chat/ — kein einziger Interim-Marker |
| Form-Builder | ✅ integriert (PR #71) | screens/forms/ — Kopf nennt „WF-P16, screens S02/S02L/S03/S05" |
| Automation / Workflow-Editor | 🟡 voller Delta-Nachzug (Davids „V1 Vollbild minimal") | screens/automation/ — 6 Screens mit Subframe-Bezug, keiner interim |
| Projekt-Pipelines | 🟡 Kernstrecke S01–S07 integriert | screens/projects/ — 7 nachgezogen, 4 noch interim (darunter das Kanban selbst) |
| Aufgaben | 🟡 Stufen 0–6 fertig | screens/tasks/ — 2 nachgezogen, 1 interim |
| Lead-Liste | 🟡 Kernstrecke (/leads = S01, /leads/inbox = S02) |
screens/leads/ — 2 nachgezogen, 6 noch interim |
Vollständig Interim — nicht als Vorbild nehmen
Kein einziger nachgezogener Screen: HR (21 Seiten), Mobile-PWA (19), CRM (6), Booking (5), DSGVO/Privacy (5), E-Mail-Postfach (4), Files (3), Kalender (2), Audit (2), Signatur, Plugins, Auth — und das Dashboard (1).
Noch gar nicht entworfen
Die zehn Auth-Flows (Login/2FA, Passwort-Reset, Set-Password, Admin-RBAC, Signup, Konto löschen, 2FA verwalten, Passwort ändern, Workspace-Auswahl, Profil & Sicherheit) stehen im Inventar auf ❌ offen — zusammen 44 Seiten.
Ergänzend: Die 30 Designer-Briefs unter .planning/designer-briefs/ haben ihren
Block „Davids Delta" durchgehend leer. Die tatsächlichen Handoffs werden
über das Flow-Inventar und die Ticket-Docs geführt, nicht über die Briefs —
102 Ticket-Docs führen einen offenen design-nachzug.
3. Was daraus für dieses Dashboard folgt
3.1 KPI-Kachel: StatsCard ist gesetzt
Die nachgezogenen Screens benutzen durchgehend ~/ui/components/StatsCard
(Billing-Übersicht, Zahlungsseite, Admin-Health, Admin-Jobs, Admin-Billing).
Die API ist knapp:
<StatsCard
trend="neutral" | "positive" | "negative"
icon={<FeatherUsers />}
label={t("…")}
value={formatters.number(totalSeats)}
percentage={t("…")} // "" um den Slot abzuschalten
/>
Unsere KPICard kann mehr: Sparkline, Akzentfarbe, richtungGut (steigender
Wert ist je nach Kennzahl gut oder schlecht), Trendlabel, ⋯-Menü zum Ausblenden.
Das ist fachlich begründet — aber es ist eine Abweichung vom gesetzten
Baustein. Beim Einbau gibt es genau zwei saubere Wege:
StatsCarderweitern und die Datei mit@subframe/sync-disableschützen (so wurde es dort schon einmal gemacht, siehe Kopf der Komponente), oder- die eigene Karte bewusst als lokale Komposition begründen.
Was nicht geht: eine zweite KPI-Kachel kommentarlos danebenstellen.
3.2 Raster: 16 px, mobil einspaltig
Das durchgängige Muster der nachgezogenen Screens:
mobile:grid-cols-1 grid w-full grid-cols-4 gap-4
gap-4 = 16 px = unser Kartenabstand ✓. Das mobile:-Präfix ist der
hauseigene Breakpoint und in 44 Stellen belegt — unser Prototyp hat kein
Mobil-Verhalten und muss es beim Einbau ergänzen.
3.3 Filterleiste: FilterBar statt Eigenbau
ProjektListPage, AutomationListPage, AutomationExecutionsPage,
FormsAdminPage und die Betriebsmittel-Übersicht nutzen alle
~/ui/components/FilterBar. Unsere AnalyticsToolbar ist handgebautes
Tailwind — funktional gleichwertig, aber am gesetzten Baustein vorbei. Das ist
die auffälligste Stelle, an der der Prototyp beim Einbau umgestellt gehört.
Bemerkenswert: Die Betriebsmittel-Übersicht wurde 2026-08-19 genau in diese
Richtung überarbeitet — „auf kompakte Kennzahlen plus echte FilterBar
umgestellt". Kennzahlenreihe über Filterleiste über Liste ist dort also bereits
das etablierte Muster. Unser Seitenaufbau folgt derselben Logik.
3.4 Weitere Konventionen der fertigen Screens
- Seitenkopf über
PageShell/PageHeader/PageBody, nie eigenes Chrome - i18n mit Namespace:
t("billing:subscriptionOverview.summary.plan") - Screen-Komponente ist rein:
({ vm, actions }), keinuseLoaderData, keinuseFetcher— Navigation und Schreibpfade sind Callbacks - Tabellen über
~/ui/components/Table, Dichte über die Komponente wählen
4. Wo es keine Leitplanke gibt: die Diagramme
Recharts kommt im gesamten Repo an drei Stellen vor: die beiden
Dashboard-Diagramme und leads/LeadAnalyticsPage.tsx. Es gibt keine geteilte
Palette, kein Chart-Theme, keine Kategorienregel — die vorhandenen Diagramme
setzen ihre Farben direkt im JSX.
Auch Davids Standards decken das nicht ab:
.planning/INTERIM-UI-DESIGN-STANDARDS.md regelt Spacing, Control-Höhen,
Dialoggrößen und Zustände sehr genau, Datenvisualisierung gar nicht.
Für dieses Dashboard heißt das beides:
- Für Kacheln, Filter, Tabellen und Seitenaufbau gibt es einen Standard — daran halten wir uns, statt ihn neu zu erfinden.
- Für Diagramme gibt es keinen. Was wir in
DESIGN-SYSTEM.md und
chartTheme.tsfestlegen, füllt eine echte Lücke und wird im Zweifel zur Referenz für alle späteren Charts. Das ist der wertvollste, aber auch der begründungspflichtigste Teil der Übergabe — deshalb steht zu jeder Regel dort, warum sie so ist.
5. Selbst nachprüfen
cd <hivegrid-cloud>
# Interim-Screens
grep -rl "Interim-UI\|AD-28" apps/web/app/components/screens --include='*Page.tsx'
# nachgezogene Screens
grep -rl "Davids\|WF-P[0-9]" apps/web/app/components/screens --include='*Page.tsx'
# autoritative Flow-Liste
cat .planning/SUBFRAME-FLOW-INVENTAR.md
Die Zahlen in diesem Dokument sind eine Momentaufnahme. Das Flow-Inventar wird fortgeschrieben (Stand dort: 2026-08-25, 12. Update) — vor einer Entscheidung lieber neu zählen.
6. Wo dieser Prototyp bewusst abweicht
Ein Abgleich mit den nachgezogenen Cloud-Screens fördert drei Stellen zutage, an denen dieser Prototyp anders arbeitet. Sie stehen hier, damit sie beim Einbau als Entscheidung erkennbar sind und nicht als Versehen wegkorrigiert werden.
| Thema | Cloud | Hier | Begründung |
|---|---|---|---|
| Zahlen in Tabellen | linksbündig; align-right nur für die Aktionsspalte |
rechtsbündig mit tabular-nums |
IBM Carbon und die eigene Planung (UI_UX_GUIDELINES.md §2) verlangen es: Nur rechtsbündig stehen Tausenderstellen untereinander, und genau darum geht es in einem Analytics-Dashboard. Die Cloud-Tabellen zeigen überwiegend Text, nicht Beträge |
| Filterleiste | ~/ui FilterBar mit Facetten-Slots |
eigene AnalyticsToolbar |
Der Prototyp braucht ein Zeitraum-Segment-Control, das die FilterBar nicht kennt. Beim Einbau ist das der erste Umbau — die Logik passt fast 1:1 auf FacetFilterBar |
| Formatierung | locale/format.ts, Prozent erwartet 0–1 |
eigene formatters.ts, Prozent erwartet 0–100 |
Der Prototyp hat keine i18n-Schicht. Beim Einbau ersetzen, aber die Achsenformatierung (achsenFormat, nettesRaster) hat dort kein Gegenstück und sollte mitkommen |
Umgekehrt übernommen wurden: keine Versalien in Spaltenköpfen, Raster mit 16 px Abstand, Kennzahlenreihe über Filterleiste über Liste, Leerzustände an jeder Visualisierung.
Bereits umgesetzt: Die Seiten sind reine ({ vm })-Komponenten mit dem
wortgleich gespiegelten VMState-Vertrag, die Berechnung liegt in reinen
Buildern unter view-models/, und die fünf Seitenzustände sind ausgestaltet.
Store-Zugriff gibt es ausschließlich in routes/ — genau der Schicht, die beim
Einbau durch den Loader ersetzt wird.
Offen für den Einbau (Portierungsarbeit, keine Gestaltung): Texte über
i18n-Keys, mobile:-Verhalten, data-ui-id auf allen Flächen, Textalternative
je Diagramm, actions-Callbacks statt Demo-Toasts. Details in
ZIELSYSTEM.md Abschnitt 3.