From 6a0b36ddccaa4f98f23d843a1d8829643a6c8162 Mon Sep 17 00:00:00 2001 From: DeeCee03 Date: Mon, 31 Aug 2026 20:51:19 +0200 Subject: [PATCH] Geviertstriche aus Text, Kommentaren und Doku entfernen MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 467 Stellen. Nicht durch einen anderen Strich ersetzt, sondern durch das Satzzeichen, das an der jeweiligen Stelle richtig ist: Doppelpunkt, wo eine Erlaeuterung folgt; Komma, wo der Satz weiterlaeuft; Punkt, wo zwei Hauptsaetze aneinanderstiessen. Ein Halbgeviertstrich waere nur derselbe Griff mit kuerzerem Strich gewesen. Regelbasiert ersetzt und danach nachgeprueft, weil eine Regel allein nicht reicht. Gefunden und einzeln korrigiert: - Eingeschobene Saetze mit Strichpaar. Nur der oeffnende Strich passte ins Muster, der schliessende blieb als "—," stehen. Drei Stellen, jetzt mit Klammern oder als eigener Satz. - Doppelte Doppelpunkte, wo beide Striche eines Paars zu Doppelpunkten wurden ("Globale Regeln: Schrift, Groessen, Abstaende: kommen aus HiveGrid"). Sieben Stellen in Doku und Oberflaeche, jetzt in Klammern. - Pfade, denen ein Komma statt eines Doppelpunkts folgte. - Ausgerichtete Kommentartabellen, in denen der Strich eine Spalte war. Nicht angefasst: drei Geviertstriche, die keine Prosa sind, sondern Tabellenplatzhalter fuer "kein Wert" (Trichter, Auftraege, Kunden). Dort ist der Strich die Angabe selbst; ihn zu entfernen liesse leere Zellen zurueck. tsc, lint, build, verify:carbon und verify:layout laufen sauber. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01QPeZNwSeU7qG3RRCwaxEZX --- HANDOVER.md | 24 +++---- README.md | 46 ++++++------ app/globals.css | 16 ++--- app/layout.tsx | 2 +- app/page.tsx | 2 +- docs/DATENMODELL.md | 24 +++---- docs/DESIGN-SYSTEM.md | 58 +++++++-------- docs/HERKUNFT.md | 22 +++--- docs/KPI-KATALOG.md | 24 +++---- docs/LEITPLANKEN.md | 62 ++++++++-------- docs/NAVIGATION.md | 34 ++++----- docs/PRUEFFRAGEN.md | 16 ++--- docs/SCOPE-ANALYTICS-DASHBOARD.md | 54 +++++++------- docs/ZIELSYSTEM.md | 72 +++++++++---------- .../dashboard/components/cards/AlertList.tsx | 6 +- .../dashboard/components/cards/ChartCard.tsx | 8 +-- .../dashboard/components/cards/KPICard.tsx | 16 ++--- .../dashboard/components/cards/StatZeile.tsx | 4 +- .../components/charts/AreaVerlauf.tsx | 2 +- .../components/charts/AuslastungsBalken.tsx | 14 ++-- .../components/charts/BalkenHorizontal.tsx | 2 +- .../components/charts/BalkenVertikal.tsx | 2 +- .../dashboard/components/charts/ChartLeer.tsx | 2 +- .../components/charts/ChartLegende.tsx | 2 +- .../components/charts/ChartTooltip.tsx | 2 +- .../dashboard/components/charts/Donut.tsx | 6 +- .../dashboard/components/charts/Trichter.tsx | 10 +-- .../components/dashboard/Begruessung.tsx | 6 +- .../dashboard/ReservierteKachel.tsx | 2 +- .../components/dashboard/WidgetKachel.tsx | 14 ++-- .../components/dashboard/WidgetRaster.tsx | 14 ++-- .../components/filters/AnalyticsToolbar.tsx | 8 +-- .../components/filters/MehrfachAuswahl.tsx | 2 +- .../components/layout/AnalyticsInnerNav.tsx | 10 +-- .../components/layout/AnalyticsShell.tsx | 4 +- .../dashboard/components/layout/AppShell.tsx | 24 +++---- .../components/layout/PageContainer.tsx | 8 +-- .../components/layout/PageHeader.tsx | 10 +-- .../dashboard/components/layout/navigation.ts | 20 +++--- .../dashboard/components/tables/DataTable.tsx | 6 +- features/dashboard/context/FilterContext.tsx | 2 +- features/dashboard/context/ToastContext.tsx | 2 +- .../dashboard/context/persistenterStore.ts | 6 +- features/dashboard/data/calculations.ts | 20 +++--- features/dashboard/data/filtering.ts | 6 +- features/dashboard/data/nutzer.ts | 4 +- features/dashboard/data/seed.ts | 20 +++--- features/dashboard/data/types.ts | 8 +-- features/dashboard/hooks/useAnalyseDaten.ts | 4 +- features/dashboard/hooks/useIstSchmal.ts | 4 +- features/dashboard/pages/AuftraegeSeite.tsx | 4 +- features/dashboard/pages/DashboardSeite.tsx | 28 ++++---- features/dashboard/pages/FinanzenSeite.tsx | 4 +- features/dashboard/pages/KomponentenSeite.tsx | 44 ++++++------ features/dashboard/pages/TeamSeite.tsx | 2 +- features/dashboard/pages/UebersichtSeite.tsx | 6 +- features/dashboard/routes/AuftraegeRoute.tsx | 2 +- features/dashboard/routes/DashboardRoute.tsx | 4 +- features/dashboard/routes/FinanzenRoute.tsx | 2 +- features/dashboard/routes/KundenRoute.tsx | 2 +- features/dashboard/routes/TeamRoute.tsx | 2 +- features/dashboard/routes/UebersichtRoute.tsx | 2 +- features/dashboard/utils/chartTheme.ts | 34 ++++----- features/dashboard/utils/dateUtils.ts | 2 +- features/dashboard/utils/formatters.ts | 4 +- .../dashboard/view-models/auftraege.vm.ts | 2 +- .../dashboard/view-models/dashboard.vm.ts | 20 +++--- .../dashboard/view-models/filter-optionen.ts | 2 +- features/dashboard/view-models/finanzen.vm.ts | 2 +- features/dashboard/view-models/index.ts | 6 +- features/dashboard/view-models/kunden.vm.ts | 4 +- features/dashboard/view-models/team.vm.ts | 6 +- .../dashboard/view-models/uebersicht.vm.ts | 2 +- scripts/verify-carbon.mjs | 10 +-- scripts/verify-layout.mjs | 10 +-- 75 files changed, 471 insertions(+), 471 deletions(-) diff --git a/HANDOVER.md b/HANDOVER.md index 35f8753..8d4b533 100644 --- a/HANDOVER.md +++ b/HANDOVER.md @@ -1,7 +1,7 @@ # Übergabe an die Entwicklung > **Rangfolge:** Wo dieser Prototyp von HiveGrid Cloud abweicht, **gilt -> HiveGrid** — Schrift, Schriftgrößen, Abstände, Farben, Control-Höhen, +> HiveGrid**: Schrift, Schriftgrößen, Abstände, Farben, Control-Höhen, > App-Shell. Dass hier dieselbe Schrift und dieselbe Seitenleisten-Komponente > stecken, dient nur der Lesbarkeit neben der Software; es ist keine Vorlage, > an der sich die Software auszurichten hätte. Verbindlich sind aus diesem Repo @@ -12,7 +12,7 @@ > **Ebenfalls vor dem Einbau lesen:** > [`docs/SCOPE-ANALYTICS-DASHBOARD.md`](docs/SCOPE-ANALYTICS-DASHBOARD.md), > insbesondere Abschnitt 3a. Der Handlungsbedarf steht dort **absichtlich -> doppelt** — auf dem Dashboard und auf der Analytics-Übersicht —, weil das +> doppelt**: auf dem Dashboard und auf der Analytics-Übersicht, weil das > Entfernen eine offene Produktfrage mitentschieden hätte. Das ist vor dem > Port aufzulösen und nicht zu übernehmen. @@ -25,13 +25,13 @@ Was echt ist, was Attrappe ist und was beim Einbau zu tun bleibt: | Bereich | Datei(en) | Zustand | |---|---|---| -| Kennzahlen-Berechnung | `features/dashboard/data/calculations.ts` | **Reine Funktionen** über typisierten Eingangsdaten — direkt übernehmbar | +| Kennzahlen-Berechnung | `features/dashboard/data/calculations.ts` | **Reine Funktionen** über typisierten Eingangsdaten: direkt übernehmbar | | Chart-Theme | `features/dashboard/utils/chartTheme.ts` | Carbon-Tokens, Palette, Achsen-Props, Margins | | Formatierung | `features/dashboard/utils/formatters.ts` | Deutsche Zahlen-, Währungs- und Datumsformate | | Chart-Komponenten | `features/dashboard/components/charts/` | Vollständig, mit Leerzuständen und Tooltips | | Karten & Tabellen | `features/dashboard/components/cards/`, `tables/` | Vollständig | | Filtersystem | `features/dashboard/context/FilterContext.tsx`, `data/filtering.ts` | State und Relevanzlogik fertig | -| Seitenaufbau | `features/dashboard/pages/` | **Reine Komponenten** `({ vm })` — kein Store-Zugriff, direkt übernehmbar | +| Seitenaufbau | `features/dashboard/pages/` | **Reine Komponenten** `({ vm })`, kein Store-Zugriff, direkt übernehmbar | | View-Model-Builder | `features/dashboard/view-models/*.vm.ts` | Reine Funktionen `(daten, filter) → VMState<…>`; im Loader wiederverwendbar | | Seitenzustände | `components/layout/SeitenZustand.tsx` | idle · loading · empty · error ausgestaltet | @@ -42,7 +42,7 @@ Was echt ist, was Attrappe ist und was beim Einbau zu tun bleibt: ### 2.1 Datenquelle austauschen Alles hängt an **einer** Stelle: `features/dashboard/data/seed.ts` exportiert -`DATENSATZ` vom Typ `Datensatz`. Diesen Export durch echte Daten ersetzen — +`DATENSATZ` vom Typ `Datensatz`. Diesen Export durch echte Daten ersetzen, Loader, Server-Query oder Service, je nach Architektur. Alle Berechnungen und Komponenten arbeiten unverändert weiter. @@ -50,7 +50,7 @@ Feldzuordnung zu den HiveGrid-Entities steht in [`docs/DATENMODELL.md`](docs/DAT **Achtung Zeitbezug:** `features/dashboard/utils/dateUtils.ts` definiert `HEUTE` als festen Stichtag (30.07.2026), damit der Prototyp reproduzierbar -bleibt. Beim Einbau durch `new Date()` ersetzen — die Konstante wird an +bleibt. Beim Einbau durch `new Date()` ersetzen, die Konstante wird an elf Stellen verwendet, alle über den Import. ### 2.2 Filter serverseitig anwenden @@ -70,7 +70,7 @@ Diese Elemente lösen bewusst nur einen Hinweis-Toast aus: | Teilen | `components/layout/PageHeader.tsx` | Link mit eingefrorenen Filtern | | Aktualisieren | `components/layout/PageHeader.tsx` | Daten neu laden | | „Als Bild exportieren" | `components/cards/ChartCard.tsx` | PNG-Export des Charts | -| Einträge in „Handlungsbedarf" | `components/cards/AlertList.tsx` | Absprung in die jeweilige Arbeitsliste — die Handlung je Zeile (`aktion`) beschreibt, was dort passieren soll | +| Einträge in „Handlungsbedarf" | `components/cards/AlertList.tsx` | Absprung in die jeweilige Arbeitsliste, die Handlung je Zeile (`aktion`) beschreibt, was dort passieren soll | | Tabellenzeilen | `components/tables/DataTable.tsx` | Absprung auf den Datensatz | | Suche und Glocke (Kopfzeile) | `components/layout/AppShell.tsx` | Attrappe, gehört zur bestehenden Shell | @@ -78,7 +78,7 @@ Diese Elemente lösen bewusst nur einen Hinweis-Toast aus: - **Zeitraum-Umschaltung** rechnet alle Kennzahlen und Charts neu, inklusive Trendvergleich zur Vorperiode - **Mehrfachfilter** (Gewerk, Status, Quelle, Region, Mitarbeiter) mit entfernbaren Chips -- **Seitenabhängige Filterrelevanz** — irrelevante Filter werden gar nicht erst angeboten +- **Seitenabhängige Filterrelevanz**: irrelevante Filter werden gar nicht erst angeboten - **Widgets ausblenden** über das ⋯-Menü jeder Karte, Wiedereinblenden über die Filterleiste, persistiert - **Tabellen** sortieren, durchsuchen, blättern - **Hover** auf Balken, Ringsegmenten, Trichterstufen und Verlaufspunkten @@ -102,12 +102,12 @@ bleiben über Reloads und Screenshots identisch, sonst ist keine Abstimmung übe konkrete Werte möglich. **Team-Seite enthalten,** obwohl die Planung sie für v2 vorgesehen hatte. -Auslastung ist im Handwerk die Kennzahl, nach der disponiert wird — ohne sie +Auslastung ist im Handwerk die Kennzahl, nach der disponiert wird, ohne sie fehlt dem Dashboard der Bezug zum Tagesgeschäft. **Kein Dark Mode.** Die Carbon-Palette ist hier im Light Theme hinterlegt. Ein Dark Theme braucht die zweite Palettenvariante (in `@carbon/charts` -enthalten) und eigene Kontrastprüfung — bewusst nicht angefangen, statt es +enthalten) und eigene Kontrastprüfung: bewusst nicht angefangen, statt es halb zu machen. --- @@ -117,7 +117,7 @@ halb zu machen. 1. `data/types.ts` gegen die echten Entity-Typen abgleichen 2. `data/seed.ts` durch die echte Datenquelle ersetzen 3. `HEUTE` in `utils/dateUtils.ts` auf `new Date()` umstellen -4. `view-models/index.ts` gegen `@hivegrid/view-models` tauschen — der Vertrag +4. `view-models/index.ts` gegen `@hivegrid/view-models` tauschen, der Vertrag (`VMState`) ist wortgleich, es ist ein Import-Wechsel 5. Eine Seite vollständig durchziehen (Übersicht): Loader ruft `baueUebersichtVM()`, die Route rendert ``. Der @@ -133,7 +133,7 @@ halb zu machen. ## 5. Offene Punkte für die Fachabstimmung - **Auslastung** rechnet produktive Stunden gegen Vertragsstunden. Ob Rüst- und - Fahrzeiten als produktiv zählen, ist eine betriebliche Festlegung — die + Fahrzeiten als produktiv zählen, ist eine betriebliche Festlegung, die Schwellen (70 % / 95 %) stehen in `components/charts/AuslastungsBalken.tsx`. - **Umsatz** ist hier Zahlungseingang, nicht Rechnungsstellung. Für die betriebswirtschaftliche Auswertung kann die andere Definition gewünscht sein; diff --git a/README.md b/README.md index 26ec307..d673051 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ -# HiveGrid Analytics Dashboard — UI/UX-Prototyp +# HiveGrid Analytics Dashboard: UI/UX-Prototyp Gestaltungsvorlage für die Analytics-Dashboards in HiveGrid, fachlich auf einen SHK-/Handwerksbetrieb zugeschnitten. **Ziel dieses Repos ist die Übergabe an die -Entwicklung** — nicht der Produktivbetrieb. +Entwicklung**, nicht der Produktivbetrieb. > **Zwei Features, nicht eines.** „Analytics" ist der Analysebereich mit fünf > Seiten und einem seitenweiten Filter; „Dashboard" ist der -> Begrüßungsbildschirm — eine Seite aus Kacheln, jede mit eigenem Zeitraum. Es +> Begrüßungsbildschirm, eine Seite aus Kacheln, jede mit eigenem Zeitraum. Es > zeigt die wichtigsten Auswertungen **plus** anderes (HR-Anträge, Aufgaben, > Termine), das noch nicht gebaut ist und im Raster als reservierte Plätze > steht. Beide sind gestaltet; offen ist, was aus der Analytics-Übersichtsseite @@ -25,14 +25,14 @@ npm run dev # http://localhost:4300 → leitet auf /dashboard | Bereich | Inhalt | |---|---| -| **5 Analyse-Seiten** | Übersicht, Finanzen, Aufträge, Kunden, Team — als Reiter im Menüpunkt **Analytics** | +| **5 Analyse-Seiten** | Übersicht, Finanzen, Aufträge, Kunden, Team, als Reiter im Menüpunkt **Analytics** | | **Seitenleiste** | spiegelt die von HiveGrid Cloud (dieselbe Komponente, dieselben Gruppen) | | **26 KPIs** | vollständig definiert in [`docs/KPI-KATALOG.md`](docs/KPI-KATALOG.md) | | **9 Chart-Bausteine** | Fläche, Säulen, liegende Balken, Ring, Trichter, Auslastung, Sparkline, Legende, Leerzustand | | **Filtersystem** | Zeitraum + 5 Dimensionen, seitenabhängig relevant, in localStorage persistiert | | **Demo-Datensatz** | deterministisch erzeugt: 420 Kunden, 1.900 Aufträge, ~1.260 Rechnungen, 2,4 Mio. € Jahresumsatz | -Alles ist deutschsprachig, weil die Oberfläche deutschsprachig ist — inklusive +Alles ist deutschsprachig, weil die Oberfläche deutschsprachig ist: inklusive Bezeichner im Code. Das erspart beim Einbau die ständige Übersetzung zwischen `revenue` und „Umsatz". @@ -41,7 +41,7 @@ Bezeichner im Code. Das erspart beim Einbau die ständige Übersetzung zwischen ## Wo was liegt ``` -app/ Next.js App Router — je Seite nur ein Wrapper +app/ Next.js App Router: je Seite nur ein Wrapper features/dashboard/ routes/ Verdrahtung Store → View-Model → Seite (wird beim Einbau durch den Loader ersetzt) @@ -57,7 +57,7 @@ features/dashboard/ data/ types · seed (Dummy-Daten) · calculations · filtering · nutzer (Attrappe des angemeldeten Benutzers) hooks/ useAnalyseDaten, useIstSchmal - pages/ die sechs Seiten — reine Komponenten ({ vm }) + pages/ die sechs Seiten: reine Komponenten ({ vm }) utils/ chartTheme (Carbon-Tokens), formatters, dateUtils ui/ Subframe-Komponentenbibliothek (unverändert übernommen) docs/ Design-System, KPI-Katalog, Navigation, Datenmodell, @@ -70,7 +70,7 @@ scripts/verify-layout.mjs misst Textkollisionen über alle Seiten und Breite (jede Kennzahl als reine Funktion) und `features/dashboard/view-models/` (je Seite ein reiner Builder `(daten, filter) → VMState<…>`). -Die Seiten unter `pages/` sind **reine Komponenten** — sie bekommen ihr +Die Seiten unter `pages/` sind **reine Komponenten**, sie bekommen ihr View-Model als Prop und greifen auf keinen Store zu. Das ist genau das Muster, das HiveGrid Cloud verlangt (``): Beim Einbau tritt der Loader an die Stelle des Containers unter `routes/`, die Seiten selbst bleiben @@ -82,15 +82,15 @@ unverändert. Details in [`docs/ZIELSYSTEM.md`](docs/ZIELSYSTEM.md) Abschnitt 3. Drei Quellen sind hier zusammengeführt: -1. **Fachliche Planung** (Januar 2026, mit dem Branchenpartner erarbeitet) — +1. **Fachliche Planung** (Januar 2026, mit dem Branchenpartner erarbeitet), Seitenschnitt, KPI-Auswahl, Filtersystem, Zahlen- und Spacing-Regeln. -2. **Bestehender Pitch-Prototyp** — die Subframe-Komponentenbibliothek unter `ui/` +2. **Bestehender Pitch-Prototyp**, die Subframe-Komponentenbibliothek unter `ui/` und die Gestaltungssprache der Oberfläche. -3. **IBM Carbon Data Visualization** — Chart-Regeln, Farbpalette, Achsen, Tooltips. +3. **IBM Carbon Data Visualization**: Chart-Regeln, Farbpalette, Achsen, Tooltips. Siehe [`docs/DESIGN-SYSTEM.md`](docs/DESIGN-SYSTEM.md). -Welche Quelle was beigesteuert hat — und an welchen Stellen bewusst von der -Januar-Planung abgewichen wurde — steht in [`docs/HERKUNFT.md`](docs/HERKUNFT.md). +Welche Quelle was beigesteuert hat, und an welchen Stellen bewusst von der +Januar-Planung abgewichen wurde: steht in [`docs/HERKUNFT.md`](docs/HERKUNFT.md). --- @@ -99,7 +99,7 @@ Januar-Planung abgewichen wurde — steht in [`docs/HERKUNFT.md`](docs/HERKUNFT. [`HANDOVER.md`](HANDOVER.md) listet auf, was echte Logik braucht, was bewusst Attrappe ist und in welcher Reihenfolge der Einbau sinnvoll ist. -Die Seite **/komponenten** zeigt jeden Baustein isoliert mit Dateipfad — der +Die Seite **/komponenten** zeigt jeden Baustein isoliert mit Dateipfad, der schnellste Weg, sich zu orientieren. ```bash @@ -113,10 +113,10 @@ einem Screenshot deshalb unsichtbar bleiben. Die Referenzwerte stehen mit Quelle und Version in [`docs/carbon-referenz.json`](docs/carbon-referenz.json), gezogen aus dem -ausgelieferten Stylesheet von `@carbon/charts` — nicht aus der Dokumentation, +ausgelieferten Stylesheet von `@carbon/charts`, nicht aus der Dokumentation, die an mehreren Stellen davon abweicht. -Für die Gestaltungsabnahme: [`docs/PRUEFFRAGEN.md`](docs/PRUEFFRAGEN.md) — +Für die Gestaltungsabnahme: [`docs/PRUEFFRAGEN.md`](docs/PRUEFFRAGEN.md), Prüffragen mit nachprüfbarem Ja/Nein, für Reviews ohne Designerauge. --- @@ -124,11 +124,11 @@ Prüffragen mit nachprüfbarem Ja/Nein, für Reviews ohne Designerauge. ## Zielsystem Eingebaut wird das hier in **HiveGrid Cloud** (`HiveGrid-Cloud`, Gitea -`toolctrl-labs`) — die eigentliche Software: pnpm-Monorepo, React Router 7, +`toolctrl-labs`), der eigentlichen Software: pnpm-Monorepo, React Router 7, Prisma/Postgres, mandantenfähig. Zielort ist der Tenant-Dashboard-Screen unter `…//dashboard`. -Dort steht bereits eine Implementierung — bewusst als **Interim-UI**: gebaut aus +Dort steht bereits eine Implementierung, bewusst als **Interim-UI**: gebaut aus derselben Subframe-Bibliothek gegen ein stabiles View-Model, damit die Backend-Tickets nicht auf den finalen Screen warten müssen. Die finale Optik ist dort als Nachzug vorgemerkt. Genau die Lücke füllt dieser Prototyp. @@ -137,18 +137,18 @@ Die Ausgangslage ist günstiger als üblich: **dasselbe Subframe-Projekt** (82 der 86 Komponenten identisch benannt) und **dieselbe Chart-Bibliothek** (Recharts). Der Einbau ist ein Port, keine Neuimplementierung. -Anzupassen sind vor allem vier Dinge — Daten kommen als View-Model-Prop mit fünf +Anzupassen sind vor allem vier Dinge: Daten kommen als View-Model-Prop mit fünf Zuständen statt als Import, Texte laufen über i18n, Diagramme brauchen eine Textalternative für Screenreader, und das App-Chrome dieses Prototyps entfällt, weil die Zielanwendung Shell und Sidebar mitbringt. **Nicht alles in der Zielanwendung sieht heute final aus.** HiveGrid Cloud arbeitet designer-first: Für jede Phase gibt es einen Brief mit den benötigten -UI-Elementen, den finalen Screen entwirft der Designer in Subframe — Layout und +UI-Elementen, den finalen Screen entwirft der Designer in Subframe: Layout und Anordnung sind ausdrücklich dessen Entscheidung. Ein großer Teil dieser Screens ist noch offen und läuft bis dahin auf Interim-UI. Für diesen Prototyp heißt das: Verbindlich zu übergeben sind **Kennzahl-Definitionen, Chart-Regeln und -Verhalten** — die Pixelanordnung ist ein Vorschlag. +Verhalten**, die Pixelanordnung ist ein Vorschlag. **Rangfolge:** Wo dieser Prototyp von HiveGrid abweicht, gilt HiveGrid. Schrift, Größen, Abstände, Farben und App-Shell kommen von dort; aus diesem Repo kommen @@ -156,6 +156,6 @@ die Kennzahl-Definitionen, die Diagrammregeln, das Verhalten und die Navigationsstruktur als Verabredung. Details, Dateipfade und die konkrete Einbau-Liste stehen in -[`docs/ZIELSYSTEM.md`](docs/ZIELSYSTEM.md) — die Rangfolge in Abschnitt 0. Welche Bereiche der Zielanwendung -bereits finale Subframe-Screens tragen — und damit als Leitplanke taugen — steht +[`docs/ZIELSYSTEM.md`](docs/ZIELSYSTEM.md): die Rangfolge in Abschnitt 0. Welche Bereiche der Zielanwendung +bereits finale Subframe-Screens tragen, und damit als Leitplanke taugen: steht in [`docs/LEITPLANKEN.md`](docs/LEITPLANKEN.md). diff --git a/app/globals.css b/app/globals.css index 4f53a3d..cd76cc8 100644 --- a/app/globals.css +++ b/app/globals.css @@ -2,13 +2,13 @@ @import "../ui/theme.css"; /* - * Schrift: Instrument Sans, selbst gehostet — identisch zur Software. + * Schrift: Instrument Sans, selbst gehostet: identisch zur Software. * * Die Dateien stammen aus `apps/web/public/fonts/` von HiveGrid Cloud, damit * Schriftschnitt und Metrik exakt übereinstimmen. Variable Schrift (400–700). * * Warum das nötig war: `ui/theme.css` verlangt für alle Subframe-Typo-Token - * bereits "Instrument Sans", die Schrift wurde aber nie geladen — und der + * bereits "Instrument Sans", die Schrift wurde aber nie geladen, und der * Fließtext war zusätzlich auf Inter gesetzt. Ergebnis waren zwei verschiedene * Schriften auf einer Seite, keine davon die der Software. */ @@ -37,7 +37,7 @@ /* * Einige Subframe-Komponenten verweisen noch direkt auf Inter. Damit sie nicht - * auf die Systemschrift zurückfallen, zeigt der Name auf dieselbe Datei — + * auf die Systemschrift zurückfallen, zeigt der Name auf dieselbe Datei, * so hält es die Software auch. */ @font-face { @@ -98,7 +98,7 @@ body { /* * `[tabindex="-1"]` ist ausgenommen: Solche Elemente sind aus der * Tabulatorreihenfolge heraus und bekommen den Fokus ausschliesslich per - * Skript — bei uns der Rahmen der Schublade, damit die Sprachausgabe den + * Skript, bei uns der Rahmen der Schublade, damit die Sprachausgabe den * Dialog anliest. Ein Ring um den ganzen Rahmen waere dort keine Orientierung, * sondern Laerm; die Orientierung gibt der naechste Tabulatorschritt. */ @@ -117,16 +117,16 @@ body { } /* - * Nachtrag zu :focus-visible — ein Fall, den der Browser falsch einschaetzt. + * Nachtrag zu :focus-visible, ein Fall, den der Browser falsch einschaetzt. * * Setzt ein Skript den Fokus, behandelt Chrome das wie Tastaturbedienung. Beim * Oeffnen und Schliessen der Schublade tun wir genau das (Fokusfalle rein, - * Fokus zurueck auf den Hamburger) — nach einem Mausklick stand der Ring + * Fokus zurueck auf den Hamburger): nach einem Mausklick stand der Ring * danach sichtbar da, bis man woanders hinklickte. * * `data-eingabe` schreibt AppShell mit: "zeiger" oder "tastatur", je nach * letzter Eingabe. Der Ring entfaellt nur waehrend Zeigerbedienung und nur an - * Knoepfen und Links. Eingabefelder sind ausgenommen — dort gehoert der Ring + * Knoepfen und Links. Eingabefelder sind ausgenommen, dort gehoert der Ring * zum Zustand "hier wird gerade geschrieben", auch nach einem Klick. Der erste * Tastendruck schaltet ihn ueberall wieder ein. */ @@ -142,7 +142,7 @@ body { * Knopf, der anklickbar ist und nichts Sichtbares bewirkt, weil er nur den * Zustand der unsichtbaren Schublade aendert. * - * Einklappen ergibt in einer Schublade ohnehin keinen Sinn — dort oeffnet und + * Einklappen ergibt in einer Schublade ohnehin keinen Sinn, dort oeffnet und * schliesst der Hamburger in der Kopfzeile. Also unterhalb `md` ausblenden. * `group/7ce7d712` ist der von Subframe erzeugte Marker des Knopf-Wrappers in * SidebarWithSections; er aendert sich nur bei einem bewussten Resync. diff --git a/app/layout.tsx b/app/layout.tsx index c2e5dc8..0e63802 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -6,7 +6,7 @@ import "./globals.css"; export const metadata: Metadata = { title: "HiveGrid · Analytics Dashboard", description: - "UI/UX-Prototyp der Analytics-Dashboards für Handwerksbetriebe (SHK) — Übergabe an die Entwicklung", + "UI/UX-Prototyp der Analytics-Dashboards für Handwerksbetriebe (SHK): Übergabe an die Entwicklung", }; export default function RootLayout({ diff --git a/app/page.tsx b/app/page.tsx index dd8bc1f..55507d1 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -2,7 +2,7 @@ import { redirect } from "next/navigation"; import { DASHBOARD_START } from "@/features/dashboard/components/layout/navigation"; /** - * Die Wurzel leitet auf das Dashboard weiter — so wie in der Software, wo + * Die Wurzel leitet auf das Dashboard weiter: so wie in der Software, wo * nach der Anmeldung der Begrüßungsbildschirm steht und nicht der * Analysebereich. * diff --git a/docs/DATENMODELL.md b/docs/DATENMODELL.md index 997b9b6..6cf8494 100644 --- a/docs/DATENMODELL.md +++ b/docs/DATENMODELL.md @@ -10,15 +10,15 @@ Einbau nur die Datenquelle getauscht werden muss. | Prototyp | HiveGrid-Entity | Verfügbar | Anmerkung | |---|---|---|---| -| `Rechnung` | **`Rechnung`** (Sub-Entity am Projekt) | v1 | Status dort `entwurf/gestellt/bezahlt/storniert` — **kein `ueberfaellig`**. Überfälligkeit wird aus `faellig_am` gegen heute abgeleitet, nicht als Status geführt | +| `Rechnung` | **`Rechnung`** (Sub-Entity am Projekt) | v1 | Status dort `entwurf/gestellt/bezahlt/storniert`: **kein `ueberfaellig`**. Überfälligkeit wird aus `faellig_am` gegen heute abgeleitet, nicht als Status geführt | | `Auftrag` | **`Projekt`** in einer Pipeline mit `typ_hint = auftrag` | v1 | „Auftrag" ist nach **AD-20 keine eigene Entität**, sondern eine Pipeline-View auf den Projekt-Kern. Wert = `auftragsvolumen`, Status = `stage_id` und damit **pipeline-intern** | | `Kunde` | **`Kontakt`** mit `kontakt_status = kunde` | v1 | „Kunde" ist ein **Status am Kontakt**, keine Entität. Kontakt ist der Oberbegriff (Privatperson/Organisation); die Verknüpfung zum Projekt läuft über `ProjektKontakt` mit Rolle `auftraggeber` | | `Mitarbeiter` | `TenantUser` + `User` | v1 | | -| `Zeiteintrag` | — | **v2** | **Zeiterfassung steht im v2-Backlog.** Damit hat die gesamte Team-Seite in v1 keine Datenquelle — siehe unten | +| `Zeiteintrag` |: | **v2** | **Zeiterfassung steht im v2-Backlog.** Damit hat die gesamte Team-Seite in v1 keine Datenquelle: siehe unten | > **Die Begriffe des Prototyps sind SHK-Fachsprache, nicht das Datenmodell der > Software.** „Auftrag" und „Kunde" existieren dort nicht als Entitäten. Das ist -> kein Fehler des Prototyps — der Betrieb spricht so, und die Oberfläche soll so +> kein Fehler des Prototyps, der Betrieb spricht so, und die Oberfläche soll so > sprechen. Beim Einbau ist es aber eine Übersetzungsleistung und keine > Eins-zu-eins-Zuordnung. @@ -30,8 +30,8 @@ Auslastung, Produktivquote, erfasste Stunden und Abwesenheiten beruhen alle auf 1. Team-Seite als v2 einplanen und in v1 nicht ausliefern; 2. Stunden aus einem Drittsystem anbinden (der Betrieb erfasst sie ohnehin - irgendwo) — dann ist es eine Integrationsfrage, keine Modellfrage; -3. Zeiterfassung nach v1 ziehen — die größte Entscheidung von den dreien. + irgendwo): dann ist es eine Integrationsfrage, keine Modellfrage; +3. Zeiterfassung nach v1 ziehen, die größte Entscheidung von den dreien. Das ist eine Produktentscheidung, keine Gestaltungsfrage. Sie gehört vor den Einbau geklärt, weil sie eine von fünf Seiten betrifft. @@ -60,7 +60,7 @@ hat. Ohne dieses Feld müsste der Trichter raten und würde die oberen Stufen systematisch zu klein zeigen. `ueberAngebot` trennt das Angebotsgeschäft (ab etwa 6.000 €) von Aufträgen, die -direkt beauftragt werden — Wartung, Notdienst, E-Check. Trichter und +direkt beauftragt werden: Wartung, Notdienst, E-Check. Trichter und Abschlussquote beziehen sich ausschließlich auf das Angebotsgeschäft. **Rechnung:** `entwurf` · `gestellt` · `bezahlt` · `ueberfaellig`. @@ -84,7 +84,7 @@ Lüftungsanlage. ## Der Demo-Datensatz -Erzeugt mit festem Seed (`mulberry32`, Seed `20260730`) — die Zahlen bleiben +Erzeugt mit festem Seed (`mulberry32`, Seed `20260730`): die Zahlen bleiben über Reloads und Screenshots identisch. Bezugsdatum ist der **30.07.2026** (`HEUTE` in `utils/dateUtils.ts`). @@ -104,15 +104,15 @@ Fiktiver Betrieb: **Meister Krause GmbH**, Raum Rhein-Main, 24 Beschäftigte **Eingebaute Effekte**, damit die Charts nicht künstlich flach aussehen: -- **Saisonalität** — Heizung und Lüftung ziehen von September bis Februar an, +- **Saisonalität**: Heizung und Lüftung ziehen von September bis Februar an, der Hochsommer ist schwächer (`SAISON_INDEX`) -- **Wachstum** — rund 12 % gegenüber dem Vorjahr -- **Größenabhängige Abschlussquote** — Wartung und Notdienst werden fast immer +- **Wachstum**, rund 12 % gegenüber dem Vorjahr +- **Größenabhängige Abschlussquote**: Wartung und Notdienst werden fast immer ausgeführt, große Anlagen dagegen verglichen und häufiger verloren -- **Zahlungsverhalten** — die Mehrheit zahlt nahe am Zahlungsziel (21 Tage), +- **Zahlungsverhalten**, die Mehrheit zahlt nahe am Zahlungsziel (21 Tage), ein kleiner Rest wird zum Mahnfall; Forderungen älter als sieben Monate sind eingebracht oder ausgebucht und stehen nicht mehr in der offenen Liste -- **Förderanträge** — nur bei Vorgängen der letzten rund 100 Tage offen; ein +- **Förderanträge**, nur bei Vorgängen der letzten rund 100 Tage offen; ein Bescheid dauert Wochen, nicht Jahre Diese Effekte sind fachlich begründet, nicht kosmetisch: Ein gleichverteilter diff --git a/docs/DESIGN-SYSTEM.md b/docs/DESIGN-SYSTEM.md index 8c36e9b..917fd59 100644 --- a/docs/DESIGN-SYSTEM.md +++ b/docs/DESIGN-SYSTEM.md @@ -4,11 +4,11 @@ Grundlage ist **IBM Carbon Data Visualization**, ergänzt um die Spacing- und Zahlenregeln aus der eigenen Planung (`UI_UX_GUIDELINES.md`, Januar 2026). Die konkreten Farb- und Linienwerte sind aus dem ausgelieferten Stylesheet von -`@carbon/charts` (Light Theme) übernommen — nicht aus der Dokumentation +`@carbon/charts` (Light Theme) übernommen, nicht aus der Dokumentation abgeschrieben. Alles Folgende ist in `features/dashboard/utils/chartTheme.ts` als Code hinterlegt. -## 0. Was Carbon regelt — und was nicht +## 0. Was Carbon regelt, und was nicht Wichtig für jeden, der hier etwas anzweifelt: **Carbon regelt Datenvisualisierung nur teilweise.** Die Grenze verläuft so: @@ -26,14 +26,14 @@ nur teilweise.** Die Grenze verläuft so: Die Carbon-Seiten zu Chart-Anatomie und Dashboards tragen ausdrücklich den Hinweis „this guidance is a work in progress" und enthalten **keine Zahlenwerte** für Abstände. Wer dort nach Paddings sucht, findet Prinzipien („create a clear -visual hierarchy", „limit the number of metrics") — richtig, aber nicht +visual hierarchy", „limit the number of metrics"): richtig, aber nicht nachprüfbar. **Die Abstandswerte in diesem Dokument stammen deshalb nicht von Carbon**, sondern aus zwei anderen Quellen: 1. der **Carbon-Spacing-Skala und dem 2x-Grid** des allgemeinen Design-Systems - (4/8/12/16/24/32/48…) — dieselbe Skala, aus der auch Davids + (4/8/12/16/24/32/48…): dieselbe Skala, aus der auch Davids `INTERIM-UI-DESIGN-STANDARDS.md` im Zielsystem schöpft; 2. der eigenen Planung mit dem Branchenpartner (`UI_UX_GUIDELINES.md`). @@ -41,7 +41,7 @@ Beides ist konsistent zueinander. Es ist aber ehrlicher zu sagen: Bei Farben und Achsen folgen wir einer Norm, bei Abständen einer begründeten Hauskonvention. **Nachprüfbar gemacht:** `npm run verify:carbon` gleicht `chartTheme.ts` gegen -`docs/carbon-referenz.json` ab — Palette, neutrale Werte, Tooltip, Achsenraster. +`docs/carbon-referenz.json` ab: Palette, neutrale Werte, Tooltip, Achsenraster. Die Referenzdatei nennt Quelle, Version und Prüfdatum. Bewusste Abweichungen (Balkenbreite, feste Kategoriefarben) sind dort begründet hinterlegt und werden als Hinweis ausgegeben, nicht als Fehler. @@ -58,7 +58,7 @@ als Hinweis ausgegeben, nicht als Fehler. 11 #009d9a 12 #012749 13 #8a3800 14 #a56eff ``` -Die Reihenfolge ist auf Unterscheidbarkeit optimiert — auch bei +Die Reihenfolge ist auf Unterscheidbarkeit optimiert, auch bei Farbfehlsichtigkeit und in Graustufen. Farben deshalb **immer von vorne vergeben**, nie nach Geschmack auswählen und nie umsortieren. @@ -76,7 +76,7 @@ keine Information mehr, sondern Dekoration. | neutral | `#8d8d8d` | | Information | `#1192e8` | -Kategorie- und Statusfarben nie im selben Chart mischen — eine grüne Kategorie +Kategorie- und Statusfarben nie im selben Chart mischen, eine grüne Kategorie neben einem grünen Positiv-Status ist nicht mehr eindeutig lesbar. **Rangfolgen einfarbig.** Top-Kunden oder Aufträge je Mitarbeiter sind keine @@ -106,7 +106,7 @@ Aussage der Grafik verwässern. Altersklassen, Risikostufen und Ähnliches sind **keine Kategorien**, sondern eine Reihenfolge mit wachsendem Risiko. Dafür gilt die vierstufige Risikorampe -(`RISIKO_RAMPE` in `chartTheme.ts`) — durchgehend Statusfarben, keine +(`RISIKO_RAMPE` in `chartTheme.ts`): durchgehend Statusfarben, keine Palettenfarbe dazwischen: | Stufe | Wert | Bedeutung | @@ -138,7 +138,7 @@ Die Vergleichsreihe ist bewusst neutral: Sie soll einordnen, nicht konkurrieren. | Y-Achsen-Breite | 58 px | Platz für „245 T€" ohne Umbruch | Bei mehr als 12 Datenpunkten wird nur jede n-te Beschriftung gezeigt, sonst -überlappen sie (`MAX_ACHSENLABELS` in `chartTheme.ts` — eine Konstante für +überlappen sie (`MAX_ACHSENLABELS` in `chartTheme.ts`, eine Konstante für alle Diagrammtypen). **Achsenwerte sind rund.** Recharts leitet Ticks aus `max/(n-1)` ab und rundet @@ -158,7 +158,7 @@ Einheitlich für alle Charts (`components/charts/ChartTooltip.tsx`), Werte aus `.cds--cc--tooltip` im ausgelieferten Stylesheet: - Fläche `#ffffff` (`--cds-layer-02`), Text `#161616` (`--cds-text-primary`) -- abgesetzt allein durch den Schatten `0 1px 6px 0 rgba(0,0,0,.2)` — **kein Rahmen** +- abgesetzt allein durch den Schatten `0 1px 6px 0 rgba(0,0,0,.2)`: **kein Rahmen** - Label und Reihenname 12 px in `#525252`, Wert fett in Tabellenziffern - kein Doppelpunkt zwischen Name und Wert, maximal 270 px breit - Farbmarker je Reihe, 10 × 10 px @@ -179,10 +179,10 @@ Ein gemeinsamer Tooltip verhindert, dass jedes Chart eigene Regeln entwickelt. | Balkenabstand | mindestens halbe Balkenbreite (`barCategoryGap: 28 %`) | | Balkenecken | 2 px, nur an der Werteseite | | Linienstärke Fläche | 2 px, Verlaufsfüllung 24 % → 2 % | -| Interpolation | **linear** — eine Monotone-Kurve erfindet Zwischenwerte zwischen zwei Messpunkten | +| Interpolation | **linear**, eine Monotone-Kurve erfindet Zwischenwerte zwischen zwei Messpunkten | | Punkte | nur beim Hovern, Radius 4, weißer Rand | | Ring innen/außen | 62 % / 88 %, 2° Segmentabstand | -| Ringmitte | Gesamtwert — sonst muss man die Segmente addieren | +| Ringmitte | Gesamtwert, sonst muss man die Segmente addieren | | Ringlegende | rechts, einzeilig, mit Wert und Prozentanteil | Ringsegmente starten oben (12 Uhr) mit dem größten Wert und laufen im @@ -190,7 +190,7 @@ Uhrzeigersinn absteigend. Auch „Sonstige" wird nach Größe einsortiert, nicht ans Ende gehängt. **Ein Ring braucht ein echtes Ganzes.** Beträgt ein Segment über 80 %, trägt die -Grafik nichts mehr bei — dann ist die Bezugsgröße falsch gewählt. Beispiel: Der +Grafik nichts mehr bei, dann ist die Bezugsgröße falsch gewählt. Beispiel: Der Rechnungsbestand aus zwei Jahren gegen den heutigen Forderungsstand ergibt 92 % „Bezahlt". Richtig ist der offene Bestand allein; dann zeigt der Ring, wie viel davon bereits überfällig ist. @@ -198,13 +198,13 @@ viel davon bereits überfällig ist. ### Werte in einem engen Band: Punkt statt Balken Auslastung liegt betrieblich zwischen etwa 70 und 100 %. Ein Balken **muss** bei -Null beginnen, sonst verzerrt seine Länge — und dann sind 74 % und 96 % optisch +Null beginnen, sonst verzerrt seine Länge, und dann sind 74 % und 96 % optisch fast gleich lang. Ein Punkt kodiert über die **Position**, nicht über die Länge, und darf deshalb einen ausgeschnittenen Bereich zeigen. Der Zielkorridor liegt als graues Band hinter den Punkten, die 100-%-Marke als beschriftete Linie, darunter eine Achse. Damit erklärt sich die Grafik ohne -Ampel-Legende — und tote Legendeneinträge („Luft frei", wenn niemand darunter +Ampel-Legende, und tote Legendeneinträge („Luft frei", wenn niemand darunter liegt) entfallen. --- @@ -239,7 +239,7 @@ zwischen den Karten, zerfällt das Raster optisch. Eine Schriftfamilie: **Instrument Sans**, selbst gehostet aus denselben Schriftdateien wie die Software (`public/fonts/`, variabel 400–700). Vorher lief der Prototyp auf Inter, während `ui/theme.css` für alle Subframe-Typo-Token -bereits „Instrument Sans" verlangte — zwei Schriften auf einer Seite, keine +bereits „Instrument Sans" verlangte: zwei Schriften auf einer Seite, keine davon die der Software. Zahlen immer in Tabellenziffern (`font-variant-numeric: tabular-nums`, global gesetzt), damit Spalten untereinander stehen. @@ -257,20 +257,20 @@ untereinander stehen. | Datum | `30.07.2026`, kurz `30.07.`, Monat `Jul 26` | Punkt als Tausendertrenner, Komma als Dezimaltrenner. Innerhalb einer Ansicht -immer dasselbe Format — nicht in einer Zeile `245.000 €` und in der nächsten +immer dasselbe Format, nicht in einer Zeile `245.000 €` und in der nächsten `245 T€`. --- ## 8. Zustände -Jedes Chart braucht einen **Leerzustand** — Filter können jede Ansicht leer +Jedes Chart braucht einen **Leerzustand**: Filter können jede Ansicht leer laufen lassen. `ChartLeer` zeigt dann eine gestrichelte Fläche mit Hinweistext statt eines leeren Rechtecks. Hover-Zustände: Karten erhalten einen stärkeren Schatten, Balken und Ringsegmente werden hervorgehoben (die übrigen auf 35–45 % Deckkraft). -Tabellenzeilen bekommen **keinen** Hover, solange sie nicht anklickbar sind — +Tabellenzeilen bekommen **keinen** Hover, solange sie nicht anklickbar sind, ein Hover ohne Ziel verspricht eine Interaktion, die es nicht gibt. ## 9. Textabstände und Umbruch @@ -287,7 +287,7 @@ zusammengehörig, bei 0 px kleben Beschriftung und Wert aneinander. schrumpft auf null, der Text bleibt stehen und läuft in das Nachbarelement. Deshalb trägt jedes Textfeld, das schrumpfen kann, entweder `truncate` (wenn Kürzen vertretbar ist) oder `break-words` (wenn nicht). Dateipfade und lange -Einzelwörter brauchen zwingend `break-words` — sie haben keine Leerzeichen zum +Einzelwörter brauchen zwingend `break-words`, sie haben keine Leerzeichen zum Umbrechen. **Legenden weichen nach unten aus.** Carbon sagt, die Legende gehört rechts @@ -295,7 +295,7 @@ neben das Diagramm, „when space is plentiful". Ist der Platz nicht reichlich, rutscht sie unter das Diagramm, statt Namen und Werte ineinanderlaufen zu lassen. Gesteuert über **Container-Queries** (`@container` / `@md:`), nicht über den Viewport: Dieselbe Karte nimmt mal ein Drittel und mal die halbe -Seitenbreite ein — der Viewport weiß davon nichts. +Seitenbreite ein, der Viewport weiß davon nichts. **Nachprüfbar gemacht:** `npm run verify:layout` lädt alle sechs Seiten in sieben Fensterbreiten (1024–1920) und misst jede Textzeile. Kollisionen unter @@ -303,7 +303,7 @@ sieben Fensterbreiten (1024–1920) und misst jede Textzeile. Kollisionen unter Warum das ein eigener Prüfer sein muss: Diese Fehler treten **nur in bestimmten Breiten** auf. Die Ringlegende auf der Finanzseite kollidierte bei 1280 und -1440 px und war bei 1600 px unauffällig — auf einem Screenshot also unsichtbar. +1440 px und war bei 1600 px unauffällig: auf einem Screenshot also unsichtbar. Auge und Einzelbild reichen dafür nicht. ## 10. Fokus und Kontrast @@ -324,7 +324,7 @@ Dropdown, Karten-Menü) schließen mit **Escape** und geben den Fokus an den auslösenden Knopf zurück. **Kontrast:** `--color-text-neutral-tertiary` liegt auf `neutral-700` -(5,15:1 auf Weiß), nicht auf `neutral-600` (3,68:1 — unter WCAG AA). Das +(5,15:1 auf Weiß), nicht auf `neutral-600` (3,68:1, unter WCAG AA). Das entspricht dem a11y-Override im Zielsystem. `text-neutral-subtle` ist ein Placeholder-Token und für lesbaren Text nicht geeignet. @@ -333,7 +333,7 @@ Placeholder-Token und für lesbaren Text nicht geeignet. ## Kartenhöhen in einer Zeile **Gestreckt wird nur, wenn die Karten einer Zeile dieselbe Bauart haben.** -Zwei Listen, zwei Zeitverläufe, zwei Tabellen — da gibt die eine Karte eine +Zwei Listen, zwei Zeitverläufe, zwei Tabellen: da gibt die eine Karte eine Höhe vor, die die andere ohnehin fast erreicht, und der Rest verteilt sich oben und unten je zur Hälfte (`justify-center` im Kartenkörper). @@ -352,7 +352,7 @@ bei 1680 px: | Vorgänge nach Status ∣ nach Gewerk (Diagramm ∣ Liste) | 190 px | **358 px** | Der Grund steckt in der Liste: Eine Balkenliste hat keine Mindesthöhe. Fünf -Kategorien ergeben 280 px, eine einzige 112 px — daneben liegt ein +Kategorien ergeben 280 px, eine einzige 112 px: daneben liegt ein Zeitverlauf unverändert bei 427 px, weil seine Diagrammfläche fest ist. Diese Zeilen zu strecken hieße, eine Karte mit einem Balken auf 427 px @@ -368,12 +368,12 @@ nach unten. **Auf dem Dashboard ist die Zeile aus Zeitverlauf und Balkenliste trotzdem gestreckt.** Das ist kein Widerspruch, sondern derselbe Maßstab: Der Unterschied entsteht dort gar nicht erst groß, weil das Dashboard keinen -Filter hat — jede Kachel zeigt ihren festen Zeitraum, die Balkenliste hat +Filter hat, jede Kachel zeigt ihren festen Zeitraum, die Balkenliste hat immer ihre fünf Gewerke, und es bleiben rund 90 px, die sich oben und unten verteilen. In Analytics kann derselbe Unterschied durch einen Filter auf 315 px wachsen. Der Filter ist der Unterschied, nicht die Kachel. -Die Karten sind in allen Fällen dynamisch — nirgends steht eine feste Höhe. +Die Karten sind in allen Fällen dynamisch: nirgends steht eine feste Höhe. Kommt mehr Inhalt hinein, wächst die Karte. --- @@ -381,13 +381,13 @@ Kommt mehr Inhalt hinein, wächst die Karte. ## Ansprache **Die Anwendung duzt.** „2 Punkte brauchen heute deine Aufmerksamkeit", nicht -„Ihre". Das gilt für jeden Text, der den Benutzer anspricht — Begrüßung, +„Ihre". Das gilt für jeden Text, der den Benutzer anspricht: Begrüßung, Leerzustände, Hinweise, Fehlermeldungen. Halb geduzt liest sich schlechter als durchgehend gesiezt: Sobald zwei Sätze auf derselben Seite unterschiedlich ansprechen, klingt die Anwendung wie von zwei Leuten geschrieben. Beim Einbau gilt im Zweifel die Ansprache von -HiveGrid — sie hat nach [ZIELSYSTEM.md](ZIELSYSTEM.md) Abschnitt 0 den Vorrang. +HiveGrid, sie hat nach [ZIELSYSTEM.md](ZIELSYSTEM.md) Abschnitt 0 den Vorrang. **Namen im Prototyp stehen in eckigen Klammern.** Die Begrüßung zeigt „Guten Tag, [Vorname]" und nicht einen erfundenen Namen. Ein fester Name sieht diff --git a/docs/HERKUNFT.md b/docs/HERKUNFT.md index e3355cf..1f2a200 100644 --- a/docs/HERKUNFT.md +++ b/docs/HERKUNFT.md @@ -19,7 +19,7 @@ absichtliche Korrektur. | **IBM Carbon Data Visualization** | Chart-Regeln, Farbpalette, Achsen, Tooltips, Kategorien-Obergrenze | laufend | Die ersten beiden liegen als lokale Ordner außerhalb dieses Repos und sind -**nicht Teil der Übergabe** — alles fachlich Relevante daraus ist in `docs/` +**nicht Teil der Übergabe**: alles fachlich Relevante daraus ist in `docs/` überführt. Die Zuordnung unten ist die Brücke zurück, falls jemand die Originale doch braucht. @@ -32,7 +32,7 @@ sind hier eingeflossen: | Teil der Planung | Wirkung in diesem Repo | |---|---| -| `01_CRM-Analytics-Clickdummy/` — React/Vite-Click-Dummy | Seitenschnitt, Komponentenzuschnitt, Filterarchitektur | +| `01_CRM-Analytics-Clickdummy/`: React/Vite-Click-Dummy | Seitenschnitt, Komponentenzuschnitt, Filterarchitektur | | `UI_UX_GUIDELINES.md` | 8-px-Raster, Regel „innen ≤ außen", Zahlenformate, KPI-Karten-Aufbau | | `03_Planung-und-Konzept/Analytics/REQUIREMENTS-analytics.md` | Anforderungs-IDs (INFRA, DASH, FIN, ORD, CUST, COMP, FILT) | @@ -45,11 +45,11 @@ Die Anforderungs-IDs stehen an mehreren Stellen als Kommentar im Code - **Fünf Analyse-Seiten** in derselben Reihenfolge: Übersicht, Finanzen, Aufträge, Kunden, Team - **Komponentenzuschnitt**: KPICard, ChartCard, AlertList, DataTable, - Filterleiste, Mehrfachauswahl mit Suche — dieselbe Aufteilung, neu geschrieben + Filterleiste, Mehrfachauswahl mit Suche: dieselbe Aufteilung, neu geschrieben - **Filterarchitektur**: globaler Filter-State über alle Seiten, in `localStorage` persistiert, aktive Einschränkungen als entfernbare Chips - **Seitenabhängige Filterrelevanz** (FILT-05) als Konzept -- **Recharts** als Chart-Bibliothek — dieselbe Wahl wie im Click-Dummy +- **Recharts** als Chart-Bibliothek: dieselbe Wahl wie im Click-Dummy - **8-px-Raster und deutsche Zahlenformate** aus `UI_UX_GUIDELINES.md`, siehe [DESIGN-SYSTEM.md](DESIGN-SYSTEM.md) Abschnitt 5 und 7 @@ -63,7 +63,7 @@ Die Anforderungs-IDs stehen an mehreren Stellen als Kommentar im Code | **Chart-Elemente** | Drop-Shadow statt Rahmen | flach, Trennung über Weißraum und Segmentabstand | Schatten auf Datenflächen erzeugen eine Tiefe, die keine Bedeutung trägt | | **Fachlichkeit** | generisches CRM: Abteilungen, Bewertungen, Kundenkontakte | SHK-Handwerk: Gewerke, Förderung, Auslastung, Angebotsgeschäft | Auftrag dieses Prototyps | | **Bezeichner** | englisch (`revenue`, `orders`) | deutsch (`umsatz`, `auftraege`) | Die Oberfläche ist deutsch. Ein Bruch in der Mitte erzwingt beim Einbau ständiges Übersetzen | -| **Datensatz** | 25 Mitarbeiter, 200 Kunden, 800 Aufträge, gleichverteilt | 24, 420, 1.900 — mit Saisonalität, Wachstum, Zahlungsverhalten | An einem gleichverteilten Datensatz lässt sich keine Gestaltung prüfen, siehe [DATENMODELL.md](DATENMODELL.md) | +| **Datensatz** | 25 Mitarbeiter, 200 Kunden, 800 Aufträge, gleichverteilt | 24, 420, 1.900: mit Saisonalität, Wachstum, Zahlungsverhalten | An einem gleichverteilten Datensatz lässt sich keine Gestaltung prüfen, siehe [DATENMODELL.md](DATENMODELL.md) | ### Anforderungen, die hier nicht umgesetzt sind @@ -75,7 +75,7 @@ fehlen vier davon bewusst: | INFRA-03 | Filter-Presets speichern und laden | Bedienkomfort ohne Gestaltungsfrage. Gehört in die echte Software ans Benutzerprofil, nicht in die Vorlage | | INFRA-04 (teilweise) | Zeitraum mit benutzerdefiniertem Bereich | Die sechs Presets decken die Abstimmung ab; ein Datumsbereichs-Picker ist eine Umsetzungs-, keine Gestaltungsfrage | | FILT-02 / FILT-04 | Filter für Rechnungsstatus und Betragsbereich | Rechnungsstatus ist auf der Finanzseite bereits als Chart-Dimension sichtbar; ein Betragsfilter verzerrt Summen-KPIs, ohne dass es an der Karte steht | -| CUST-03 | KPI „Kontakte gesamt" | Der Prototyp führt keine Kontakt-Entität. In HiveGrid existiert sie — die Karte lässt sich beim Einbau ergänzen | +| CUST-03 | KPI „Kontakte gesamt" | Der Prototyp führt keine Kontakt-Entität. In HiveGrid existiert sie, die Karte lässt sich beim Einbau ergänzen | Umgekehrt ist **Team** enthalten, obwohl die Planung es unter v2 führt (TEAM-01 bis TEAM-03): Auslastung ist im Handwerk die Kennzahl, nach der @@ -90,10 +90,10 @@ gesamte Oberfläche außerhalb der Diagramme. | Übernommen | Wo | |---|---| -| Komponentenbibliothek — 86 Komponenten, 4 Layouts | `ui/components/`, `ui/layouts/` | +| Komponentenbibliothek: 86 Komponenten, 4 Layouts | `ui/components/`, `ui/layouts/` | | Design-Tokens (Farben, Radien, Schatten, Typo-Skala) | `ui/theme.css`, eingebunden in `app/globals.css` | | Icon-Set (Feather über `@subframe/core`) | überall, aufgelöst in `components/layout/FeatherIcon.tsx` | -| Stack | Next.js 16 · React 19 · Tailwind v4 — gleiche Versionen | +| Stack | Next.js 16 · React 19 · Tailwind v4: gleiche Versionen | `ui/` ist **byteidentisch** mit dem Stand im Pitch-Repo und wurde nicht angefasst. Die Bibliothek wird dort über die Subframe-CLI aus dem Projekt @@ -104,7 +104,7 @@ npx @subframe/cli@latest sync --all ``` Wer die Bibliothek aktualisiert, sollte das im Pitch-Repo tun und den Ordner -hierher kopieren — sonst laufen die beiden Stände auseinander. +hierher kopieren, sonst laufen die beiden Stände auseinander. ### Was aus der Bibliothek nicht verwendet wird @@ -115,7 +115,7 @@ Carbon-Regeln umzusetzen. Die Diagramme unter `features/dashboard/components/charts/` setzen deshalb direkt auf Recharts auf. Das ist die einzige Stelle, an der dieser Prototyp von der Pitch-Bibliothek -abweicht — überall sonst gilt sie. +abweicht: überall sonst gilt sie. --- @@ -126,7 +126,7 @@ Grundlage aller Diagramm-Entscheidungen. Ausformuliert in `features/dashboard/utils/chartTheme.ts`. Die Farb- und Linienwerte sind aus dem ausgelieferten Stylesheet von -`@carbon/charts` (`dist/styles.css`, Light Theme) übernommen — nicht aus der +`@carbon/charts` (`dist/styles.css`, Light Theme) übernommen, nicht aus der Dokumentation abgeschrieben. Das Paket selbst ist **keine Abhängigkeit** dieses Repos; gezogen wurden nur die Werte. diff --git a/docs/KPI-KATALOG.md b/docs/KPI-KATALOG.md index 043c459..751517f 100644 --- a/docs/KPI-KATALOG.md +++ b/docs/KPI-KATALOG.md @@ -5,8 +5,8 @@ Alle Funktionen liegen in `features/dashboard/data/calculations.ts`. **Zwei Zeitbezüge sind zu unterscheiden:** -- **zeitraumbezogen** — reagiert auf die Zeitraum-Umschaltung (Umsatz, neue Kunden) -- **stichtagsbezogen** — gilt zum heutigen Tag, unabhängig vom Zeitraum +- **zeitraumbezogen**: reagiert auf die Zeitraum-Umschaltung (Umsatz, neue Kunden) +- **stichtagsbezogen**: gilt zum heutigen Tag, unabhängig vom Zeitraum (offene Forderungen, aktive Aufträge, Auslastung des Bestands) Das ist Absicht: „Offene Forderungen der letzten 7 Tage" wäre keine sinnvolle @@ -14,7 +14,7 @@ Zahl. In der Oberfläche steht der Zeitbezug in der **Fußzeile jeder KPI-Karte** („im gewählten Zeitraum" / „zum Stichtag" / „über alle Zeiträume"). Karten mit -Vorperiodenvergleich zeigen dort stattdessen den Trend — die Anatomie bleibt +Vorperiodenvergleich zeigen dort stattdessen den Trend, die Anatomie bleibt gleich, damit die Reihe eine gemeinsame Grundlinie hat. Diagrammkarten, die den Zeitraumfilter ignorieren, sagen es im Untertitel. @@ -35,7 +35,7 @@ den Zeitraumfilter ignorieren, sagen es im Untertitel. **Umsatzentwicklung** (`umsatzVerlauf()`) bildet zusätzlich den Vorjahreszeitraum ab: Jede Zahlung wird um zwölf Monate verschoben in denselben -Zeitraster einsortiert. Die Auflösung wechselt automatisch — bis 30 Tage +Zeitraster einsortiert. Die Auflösung wechselt automatisch, bis 30 Tage tageweise, darüber monatsweise. --- @@ -73,7 +73,7 @@ grün nach rot eingefärbt. | Vertriebstrichter | Vorgänge je erreichter Stufe | Stichtag | `vertriebsTrichter()` | | Förderquote BAFA/KfW | Anteil **förderfähiger** Aufträge mit beantragter oder bewilligter Förderung | Stichtag | `foerderQuote()` | -**Zum Trichter:** Er zeigt ausschließlich das **Angebotsgeschäft** — Vorhaben +**Zum Trichter:** Er zeigt ausschließlich das **Angebotsgeschäft**: Vorhaben ab etwa 6.000 €, für die schriftlich angeboten wird (Feld `ueberAngebot`). Wartung, Notdienst und E-Check gehen ohne Angebot direkt in die Ausführung; zählte man sie mit, würde der Trichter unten breiter als oben. @@ -83,12 +83,12 @@ Verlorene Vorgänge zählen bis zu der Stufe, auf der sie abgesprungen sind systematisch zu klein und die Übergangsquoten wertlos. **Zur Abschlussquote:** gleiche Bezugsgröße wie der Trichter. Sie entspricht -deshalb exakt der Übergangsquote von „Angebot" auf „Beauftragt" — im +deshalb exakt der Übergangsquote von „Angebot" auf „Beauftragt": im Demo-Datensatz rund 38 %. **Zur Förderquote:** Bezugsgröße sind nur förderfähige Leistungen (Wärmepumpe, PV-Anlage, Batteriespeicher, Lüftungsanlage). Über alle Aufträge gerechnet läge -sie im einstelligen Bereich und wäre wertlos — eine Badsanierung war nie +sie im einstelligen Bereich und wäre wertlos, eine Badsanierung war nie förderfähig. --- @@ -97,7 +97,7 @@ förderfähig. | KPI | Definition | Bezug | Funktion | |---|---|---|---| -| Kunden gesamt | Alle Kundendatensätze | Stichtag | — | +| Kunden gesamt | Alle Kundendatensätze | Stichtag |: | | Neue Kunden | Anlagedatum im Zeitraum | Zeitraum | `neueKunden()` | | Wiederkehrende Kunden | Anteil mit mehr als einem Auftrag | Stichtag | `wiederkehrquote()` | | Ø Kundenwert | Bezahlter Umsatz je Kunde mit mindestens einem Auftrag | gesamt | abgeleitet | @@ -106,7 +106,7 @@ förderfähig. | Auffällige Zahlungsmoral | Ø Zahlungsdauer über 30 Tage | Stichtag | `zahlungsauffaellig()` | Empfehlung und Bestandskunden zusammen zeigen, wie stark der Betrieb ohne -Werbebudget wächst — im Handwerk die aussagekräftigste Quellenkennzahl. +Werbebudget wächst, im Handwerk die aussagekräftigste Quellenkennzahl. --- @@ -114,7 +114,7 @@ Werbebudget wächst — im Handwerk die aussagekräftigste Quellenkennzahl. | KPI | Definition | Bezug | Funktion | |---|---|---|---| -| Im Einsatz | Gewerblich Beschäftigte mit Status „aktiv" | Stichtag | — | +| Im Einsatz | Gewerblich Beschäftigte mit Status „aktiv" | Stichtag |: | | Ø Auslastung | Produktive Stunden / verfügbare Stunden (aus Wochenstunden hochgerechnet) | Zeitraum | `teamKennzahlen()` | | Produktivquote | Auftragsbezogene Stunden / erfasste Stunden | Zeitraum | abgeleitet | | Erfasste Stunden | Summe aller Zeiteinträge | Zeitraum | abgeleitet | @@ -126,9 +126,9 @@ Werbebudget wächst — im Handwerk die aussagekräftigste Quellenkennzahl. | Bereich | Bedeutung | |---|---| -| < 70 % | Luft frei — Kapazität ungenutzt | +| < 70 % | Luft frei: Kapazität ungenutzt | | 70–95 % | Zielkorridor | -| > 95 % | Ausgebucht — Terminrisiko | +| > 95 % | Ausgebucht: Terminrisiko | Der Auftragswert je Mitarbeiter ist ausdrücklich **kein Leistungsvergleich**: Ein Wärmepumpen-Auftrag ist um ein Vielfaches größer als eine Wartung. Der diff --git a/docs/LEITPLANKEN.md b/docs/LEITPLANKEN.md index b566a4a..1fcbd08 100644 --- a/docs/LEITPLANKEN.md +++ b/docs/LEITPLANKEN.md @@ -1,12 +1,12 @@ # 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 +Welche Bereiche der Zielanwendung bereits Davids finale Subframe-Screens tragen, +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 +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. @@ -20,62 +20,62 @@ 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 | +| `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` +> `// 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` +> `// 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**, +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), +**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 +### 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 | +| **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 +### 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 — +**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. +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 — +über das Flow-Inventar und die Ticket-Docs geführt, nicht über die Briefs, 102 Ticket-Docs führen einen offenen `design-nachzug`. --- @@ -100,7 +100,7 @@ Die API ist knapp: 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 +Das ist fachlich begründet: **aber es ist eine Abweichung vom gesetzten Baustein.** Beim Einbau gibt es genau zwei saubere Wege: 1. `StatsCard` erweitern und die Datei mit `@subframe/sync-disable` schützen @@ -118,7 +118,7 @@ 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 +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 @@ -126,11 +126,11 @@ Mobil-Verhalten und muss es beim Einbau ergänzen. `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 +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` +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. @@ -139,7 +139,7 @@ das etablierte Muster. Unser Seitenaufbau folgt derselben Logik. - Seitenkopf über `PageShell` / `PageHeader` / `PageBody`, nie eigenes Chrome - i18n mit Namespace: `t("billing:subscriptionOverview.summary.plan")` - Screen-Komponente ist rein: `({ vm, actions })`, kein `useLoaderData`, - kein `useFetcher` — Navigation und Schreibpfade sind Callbacks + kein `useFetcher`: Navigation und Schreibpfade sind Callbacks - Tabellen über `~/ui/components/Table`, Dichte über die Komponente wählen --- @@ -148,7 +148,7 @@ das etablierte Muster. Unser Seitenaufbau folgt derselben Logik. 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 +Palette, kein Chart-Theme, keine Kategorienregel, die vorhandenen Diagramme setzen ihre Farben direkt im JSX. Auch Davids Standards decken das nicht ab: @@ -157,12 +157,12 @@ 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 — +- 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](DESIGN-SYSTEM.md) und `chartTheme.ts` festlegen, 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 — + der wertvollste, aber auch der begründungspflichtigste Teil der Übergabe, deshalb steht zu jeder Regel dort, warum sie so ist. --- @@ -183,7 +183,7 @@ 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 +fortgeschrieben (Stand dort: 2026-08-25, 12. Update). Vor einer Entscheidung lieber neu zählen. --- @@ -192,7 +192,7 @@ lieber neu zählen. > Vorab, damit die folgende Tabelle nicht falsch gelesen wird: **Eine bewusste > Abweichung ist eine Bitte um eine Entscheidung, kein Freibrief.** Bei -> globalen Regeln — Schrift, Größen, Abstände, Farben, Control-Höhen — gilt +> globalen Regeln (Schrift, Größen, Abstände, Farben, Control-Höhen) gilt > ohne Diskussion HiveGrid. Die Punkte unten betreffen ausschließlich den > Analytics-Bereich und sind begründet, damit sie beim Einbau nicht > versehentlich „korrigiert" werden. Rangfolge: [ZIELSYSTEM.md](ZIELSYSTEM.md) @@ -205,7 +205,7 @@ 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` | +| **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 @@ -215,7 +215,7 @@ 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 +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 diff --git a/docs/NAVIGATION.md b/docs/NAVIGATION.md index d77bf23..5fea90b 100644 --- a/docs/NAVIGATION.md +++ b/docs/NAVIGATION.md @@ -4,12 +4,12 @@ Die Seitenleiste zeigt **nur unsere beiden Features**. Kontakte, Leads, Pipelines, Postfach, Termine und Einstellungen stehen bereits in der -Seitenleiste der Software und werden hier nicht verdoppelt — der Prototyp zeigt, +Seitenleiste der Software und werden hier nicht verdoppelt, der Prototyp zeigt, was dazukommt, nicht was schon da ist. ``` HIVEGRID -├── Dashboard Begrüßungsbildschirm — Widget-Fläche /dashboard +├── Dashboard Begrüßungsbildschirm: Widget-Fläche /dashboard └── Analytics ◄── der Prototyp lebt hier /analytics ├───────────────────── └── Komponenten Bausteingalerie des Prototyps /komponenten @@ -19,12 +19,12 @@ Gerendert wird mit derselben Komponente wie in der Software (`ui/components/SidebarWithSections`, aus der Cloud-Fassung portiert) und derselben Schrift (Instrument Sans, selbst gehostet aus denselben Dateien). -> **Für den Einbau:** Verbindlich ist an dieser Seitenleiste die **Struktur** — +> **Für den Einbau:** Verbindlich ist an dieser Seitenleiste die **Struktur**, > zwei Einträge, Analytics mit innerer Leiste. Nicht verbindlich ist ihre > Umsetzung hier. In der Software werden die zwei Einträge in die bestehende > `AppSidebar` eingehängt und die innere Leiste über das dortige > `SidebarIconsLayout` gebaut; unser Nachbau wird nicht mitportiert. Globale -> Regeln — Schrift, Größen, Abstände, Farben — kommen ausschließlich aus +> Regeln (Schrift, Größen, Abstände, Farben) kommen ausschließlich aus > HiveGrid und werden von hier aus **nicht** überschrieben. Siehe > [ZIELSYSTEM.md](ZIELSYSTEM.md) Abschnitt 0. @@ -39,8 +39,8 @@ Analyse-Seiten sind darin über eine **innere Leiste** erreichbar: /analytics/team Team ``` -Zwei Navigationsebenen für dieselbe Sache — Unterpunkte in der Seitenleiste -*und* eine innere Leiste — würden nur konkurrieren. +Zwei Navigationsebenen für dieselbe Sache: Unterpunkte in der Seitenleiste +*und* eine innere Leiste: würden nur konkurrieren. ### Warum innere Leiste und nicht Reiter @@ -49,9 +49,9 @@ Beides gibt es im Zielsystem, aber für verschiedene Aufgaben: | | innere Leiste (`SidebarIconsLayout`) | Reiter (`Tabs`) | |---|---|---| | Wofür | Arbeitsbereich mit **Geschwisterseiten** | Abschnitte **innerhalb einer Seite** | -| Beispiele | Leads, Termine, HR, Einstellungen — 17 Aufrufstellen | Formular-Editor, Chat-Dateien, Projekt-Teilbereiche, Übergabe-Dialog | +| Beispiele | Leads, Termine, HR, Einstellungen: 17 Aufrufstellen | Formular-Editor, Chat-Dateien, Projekt-Teilbereiche, Übergabe-Dialog | -Analytics mit fünf Analyse-Seiten ist der erste Fall — strukturell dasselbe wie +Analytics mit fünf Analyse-Seiten ist der erste Fall: strukturell dasselbe wie Leads mit seinen acht. Drei Gründe geben den Ausschlag: 1. **Kohärenz.** Wer in der Software von Leads nach Analytics wechselt, findet @@ -59,7 +59,7 @@ Leads mit seinen acht. Drei Gründe geben den Ausschlag: 2. **Der Platzeinwand trägt nicht.** Die Leiste ist standardmäßig eine 32 px schmale Icon-Spalte und klappt erst bei Zeigerkontakt oder Tastaturfokus auf Beschriftungen aus (verzögert, damit sie beim Überstreichen nicht - aufspringt). Sie kostet also kaum Breite — und die brauchen die + aufspringt). Sie kostet also kaum Breite, und die brauchen die Analyse-Seiten mit ihren fünfspaltigen Kennzahlenreihen und breiten Tabellen. 3. **Reiter sind dort der Rückfall, nicht die Wahl.** `SidebarIconsLayout` zeigt unterhalb `sm` selbst eine Reiterleiste. Auf dem Schreibtisch Reiter zu @@ -67,23 +67,23 @@ Leads mit seinen acht. Drei Gründe geben den Ausschlag: übernimmt diesen Rückfall mit. Ein weiterer Vorteil: Die Leiste wächst. Käme eine sechste Analyse-Seite dazu, -ist das eine Zeile mehr — ein Reiterband würde eng. +ist das eine Zeile mehr, ein Reiterband würde eng. „Dashboard" führt auf den **Begrüßungsbildschirm** unter `/dashboard`. Er hat bewusst **keine innere Leiste und keine Filterleiste**: Er ist eine einzelne Seite aus Kacheln, und jede Kachel trägt ihren eigenen Zeitraum. Das ist der -sichtbarste Unterschied zwischen den beiden Menüpunkten — Analytics ist ein +sichtbarste Unterschied zwischen den beiden Menüpunkten: Analytics ist ein Bereich, das Dashboard eine Seite. Siehe [SCOPE-ANALYTICS-DASHBOARD.md](SCOPE-ANALYTICS-DASHBOARD.md). ### Schmale Fenster -Unterhalb **768 px** — derselbe Breakpoint, den die Software als `MOBILE_BREAKPOINT` -führt — fährt die Seitenleiste als Schublade über den Inhalt, statt ihn zu +Unterhalb **768 px**: derselbe Breakpoint, den die Software als `MOBILE_BREAKPOINT` +führt: fährt die Seitenleiste als Schublade über den Inhalt, statt ihn zu verdrängen. Geöffnet wird sie über einen Hamburger links in der Kopfzeile. Das ist **nicht erfunden, sondern abgeglichen**: `SubframeAppShell` im -Zielsystem rendert an derselben Stelle denselben Knopf — `FeatherMenu`, 32 × 32, +Zielsystem rendert an derselben Stelle denselben Knopf: `FeatherMenu`, 32 × 32, `md:hidden`, links vor dem Breadcrumb. Übernommen wurden auch das Verhalten der Schublade (Abdeckung dahinter, Escape schließt, Fokus wandert beim Öffnen auf den ersten Eintrag und kehrt beim Schließen zum Auslöser zurück) und die @@ -128,14 +128,14 @@ es sich entwickelt? → Woran liegt es?** Auf der **Übersicht** steht der Handlungsbedarf direkt unter der KPI-Reihe und über die volle Breite. Sie ist die Seite der Geschäftsführung; dort ist „was ist zu tun" die zweite Frage, nicht die letzte. Jede Zeile trägt Betrag und Handlung -(„Mahnlauf starten", „Nachfassen") — eine Liste ohne Verb ist ein Bericht. +(„Mahnlauf starten", „Nachfassen"): eine Liste ohne Verb ist ein Bericht. Auf den vier Detailseiten bleibt die Arbeitsliste unten: Dort ist sie die Konsequenz aus dem, was darüber steht. **Gleiche Kartenhöhe nur bei gleicher Struktur.** Die KPI-Reihe wird gestreckt, damit die fünf Karten als ein Objekt lesbar sind. Gemischte Reihen (Diagramm -mit fester Höhe neben Tabelle) stehen auf `items-start` — Strecken erzeugt dort +mit fester Höhe neben Tabelle) stehen auf `items-start`: Strecken erzeugt dort nur Weißraum. --- @@ -173,5 +173,5 @@ Definiert in `features/dashboard/data/filtering.ts`: | Team | ✓ | ✓ | | | | ✓ | Ein Filter, der sichtbar ist aber nichts bewirkt, kostet Vertrauen in die -Zahlen. Deshalb werden irrelevante Filter gar nicht erst angeboten — die +Zahlen. Deshalb werden irrelevante Filter gar nicht erst angeboten, die Auswahl bleibt aber im Hintergrund erhalten und wirkt beim Seitenwechsel wieder. diff --git a/docs/PRUEFFRAGEN.md b/docs/PRUEFFRAGEN.md index b2613c0..8e112e4 100644 --- a/docs/PRUEFFRAGEN.md +++ b/docs/PRUEFFRAGEN.md @@ -1,7 +1,7 @@ # Prüffragen für die Gestaltungsabnahme Für Reviews ohne Designerauge. Die Fragen sind so gestellt, dass man sie am -Bildschirm beantworten kann — jede hat ein nachprüfbares Ja oder Nein, keine +Bildschirm beantworten kann, jede hat ein nachprüfbares Ja oder Nein, keine Geschmacksfrage. Reihenfolge nach Wirkung: Wer nur zehn Minuten hat, nimmt Abschnitt 1. @@ -33,7 +33,7 @@ Handlungsliste braucht je Zeile einen Betrag und ein Verb. | Frage | Wenn nein | |---|---| -| Beginnt jede Balkenachse bei null? | Balken kodieren über Länge — abgeschnitten lügen sie. Bei engen Wertebändern Punktdiagramm statt Balken | +| Beginnt jede Balkenachse bei null? | Balken kodieren über Länge: abgeschnitten lügen sie. Bei engen Wertebändern Punktdiagramm statt Balken | | Hat jede Achse runde Werte (0/50/100, nicht 0/55/110)? | Der Leser rechnet bei jedem Blick mit | | Trägt eine Achse genau eine Einheit? | „0 €" neben „10 T€" ist ein Einheitenwechsel mitten in der Skala | | Belegt in einem Ring kein Segment mehr als etwa 80 %? | Dann ist die Bezugsgröße falsch gewählt, nicht der Diagrammtyp | @@ -58,7 +58,7 @@ Handlungsliste braucht je Zeile einen Betrag und ein Verb. ## 4. Layout, Raster und Zustände **Vor jedem Review `npm run verify:layout` laufen lassen.** Der Prüfer findet -kollidierenden und überlaufenden Text über sieben Fensterbreiten — das ist die +kollidierenden und überlaufenden Text über sieben Fensterbreiten, das ist die eine Fehlerklasse, die man mit dem Auge zuverlässig übersieht, weil sie nur in bestimmten Breiten auftritt. @@ -81,11 +81,11 @@ Ringlegenden, Achsenbeschriftungen und Tabellenköpfe achten. Kurz und ergiebig, in dieser Reihenfolge: -1. **FT Visual Vocabulary** — ein Poster, das Diagrammtypen nach Aussageabsicht +1. **FT Visual Vocabulary**, ein Poster, das Diagrammtypen nach Aussageabsicht ordnet (Vergleich, Verteilung, Anteil, Veränderung …). Das beste Verhältnis von Aufwand zu Ertrag überhaupt. `github.com/Financial-Times/chart-doctor` → `visual-vocabulary` -2. **IBCS — International Business Communication Standards**, die SUCCESS-Regeln. +2. **IBCS: International Business Communication Standards**, die SUCCESS-Regeln. Das ist der ausgearbeitete Standard für *Geschäfts*grafik, den Carbon nicht ersetzt: einheitliche Notation, Ist/Plan/Vorjahr, Informationsdichte. Frei unter CC BY-SA auf `ibcs.com`. @@ -95,14 +95,14 @@ Kurz und ergiebig, in dieser Reihenfolge: warum Ringe schwach und Punktdiagramme stark sind. 4. **Stephen Few, „Information Dashboard Design"**. Das Standardwerk zur Dashboard-Kritik; die ersten beiden Kapitel reichen für ein geschultes Auge. -5. **Datawrapper Academy** (`academy.datawrapper.de`) — kurze, gut belegte +5. **Datawrapper Academy** (`academy.datawrapper.de`): kurze, gut belegte Artikel zu einzelnen Fragen („Wann Balken, wann Linien", „Warum keine zwei Y-Achsen"). Zum Zielsystem passend: 6. **Carbon Data Visualization** (`carbondesignsystem.com/data-visualization/`) - für Farben, Achsen und Diagrammtypen — mit der Einschränkung aus + für Farben, Achsen und Diagrammtypen, mit der Einschränkung aus [DESIGN-SYSTEM.md](DESIGN-SYSTEM.md) Abschnitt 0: Abstände regelt Carbon nicht. 7. **Carbon Spacing und 2x-Grid** (`carbondesignsystem.com/elements/spacing/`) für genau diese Abstände. @@ -114,4 +114,4 @@ Zum Zielsystem passend: Layout und Anordnung sind im Zielsystem **Entscheidung des Designers** (siehe [LEITPLANKEN.md](LEITPLANKEN.md)). Verbindlich zu übergeben sind Kennzahl-Definitionen, Diagrammregeln und Verhalten. Wer diese Liste im Review -benutzt, prüft die Substanz — nicht, ob eine Karte 40 px weiter links sitzt. +benutzt, prüft die Substanz, nicht, ob eine Karte 40 px weiter links sitzt. diff --git a/docs/SCOPE-ANALYTICS-DASHBOARD.md b/docs/SCOPE-ANALYTICS-DASHBOARD.md index d4ae06e..47ec520 100644 --- a/docs/SCOPE-ANALYTICS-DASHBOARD.md +++ b/docs/SCOPE-ANALYTICS-DASHBOARD.md @@ -2,14 +2,14 @@ **Stand: 31.08.2026.** Entschieden und gebaut sind die Navigation (5.5) und der erste Aufschlag des Dashboards (Abschnitt 3a). Offen und mit den Kollegen -zu klären bleiben 5.1, 5.3 und 5.6 — sie betreffen eine **Doppelung, die +zu klären bleiben 5.1, 5.3 und 5.6: sie betreffen eine **Doppelung, die gerade absichtlich im Repo steht** und in Abschnitt 3a benannt ist. --- ## 1. Die Unterscheidung -Bisher wurde dieser Prototyp als „das Dashboard" bezeichnet. Das ist ungenau — +Bisher wurde dieser Prototyp als „das Dashboard" bezeichnet. Das ist ungenau, es sind zwei Features mit unterschiedlichem Zweck: | | **Analytics** | **Dashboard** | @@ -23,7 +23,7 @@ es sind zwei Features mit unterschiedlichem Zweck: **Der entscheidende Unterschied:** Das Dashboard zeigt die wichtigsten Charts aus Analytics, ist aber **nicht darauf beschränkt**. Es ist der Ort für alles, -was beim Anmelden zählt — auch für Dinge, die keine Auswertung sind: +was beim Anmelden zählt, auch für Dinge, die keine Auswertung sind: „2 neue Anträge", offene Dokumente, Termine heute, zugewiesene Aufgaben. Analytics liefert also Bausteine an das Dashboard, deckt es aber nicht ab. @@ -32,7 +32,7 @@ Analytics liefert also Bausteine an das Dashboard, deckt es aber nicht ab. ## 2. Was die Software dafür bereits vorsieht -Das ist kein neuer Scope für HiveGrid Cloud — die Architektur ist darauf +Das ist kein neuer Scope für HiveGrid Cloud, die Architektur ist darauf ausgelegt. Belegt in `packages/view-models/src/dashboard/dashboard-page.vm.ts`: ```ts @@ -43,7 +43,7 @@ type DashboardWidgetKind = "hero" | "kpi" | "list" | "trend" | "chart"; ``` Die Domäne **`hr`** und die Art **`list`** existieren bereits. „2 neue Anträge" -ist damit ein `hr`/`kpi`- oder `hr`/`list`-Widget im Katalog — kein Sonderfall, +ist damit ein `hr`/`kpi`- oder `hr`/`list`-Widget im Katalog, kein Sonderfall, sondern der vorgesehene Weg. Der Designer-Brief P11 nennt die drei Rollen-Layouts sogar konkret: @@ -61,7 +61,7 @@ dokumentiert; was fehlt, ist die Verbindung zu unserer Analytics-Arbeit. ## 3. Was das für diesen Prototyp bedeutet **Die fünf Analyse-Seiten sind das Analytics-Feature.** Daran ändert sich -nichts — Finanzen, Aufträge, Kunden, Team und die Diagrammbausteine bleiben, +nichts: Finanzen, Aufträge, Kunden, Team und die Diagrammbausteine bleiben, wie sie sind. **Drei Stellen bekommen einen anderen Zuschnitt:** @@ -74,13 +74,13 @@ wie sie sind. 2. **Der Handlungsbedarf ist eigentlich ein Dashboard-Element.** „Was ist zu tun" ist die Frage des Begrüßungsbildschirms, nicht der Analyse. Ich habe ihn in der letzten Runde bewusst nach oben auf die Übersicht - gezogen, weil dort die Handlungsebene fehlte — unter der neuen Trennung + gezogen, weil dort die Handlungsebene fehlte: unter der neuen Trennung gehört er wahrscheinlich ins Dashboard. 3. **Charts müssen als Widgets einzeln funktionieren.** Gute Nachricht: Sie tun es bereits. Die Diagrammkomponenten unter `components/charts/` sind reine Komponenten, die ihre Daten als Prop - bekommen — sie hängen an keiner Seite. Was **nicht** mitwandert, ist die + bekommen, sie hängen an keiner Seite. Was **nicht** mitwandert, ist die Kartenhülle `ChartCard`: Ihr ⋯-Menü und das Ausblenden sind Analytics-Logik; im Dashboard macht das die Widget-Registry. @@ -88,14 +88,14 @@ wie sie sind. Filterleiste auf alle Karten gleichzeitig. Im Dashboard trägt jedes Widget seinen eigenen Zeitraum (P11: „Edit = nur Widget-Filter/Zeitraum"). Ein Chart, das aus Analytics ins Dashboard gehoben wird, verliert den globalen - Filter und braucht einen eigenen — sonst zeigt es stillschweigend einen + Filter und braucht einen eigenen, sonst zeigt es stillschweigend einen anderen Zeitraum als die Nachbarkachel. --- ## 3a. Was am 31.08.2026 gebaut wurde -Das Dashboard existiert unter `/dashboard` — als **erster Aufschlag mit +Das Dashboard existiert unter `/dashboard`, als **erster Aufschlag mit Analytics-Inhalten**, aber als Widget-Fläche gebaut, nicht als Analytics-Seite mit anderem Titel. @@ -129,11 +129,11 @@ bearbeitbar. *Eine Zeile fehlt der Software dafür:* `dashboardWidgetGridClass` kennt keinen Fall `position.x === 9`, weil bisher keine Rolle vier Kacheln nebeneinander stellt. Unsere Kennzahlenreihe tut das. Ohne die Zeile fließt die vierte -Kachel dank `grid-flow-row-dense` trotzdem an die richtige Stelle — nur ohne +Kachel dank `grid-flow-row-dense` trotzdem an die richtige Stelle, nur ohne festen Anfang. Vermerkt in `components/dashboard/WidgetRaster.tsx`. **Die späteren Bereiche stehen nicht auf dem Dashboard.** Ein -Begrüßungsbildschirm ist kein Ort für Ankündigungen — wer sich morgens +Begrüßungsbildschirm ist kein Ort für Ankündigungen, wer sich morgens anmeldet, will seine Lage sehen und nicht lesen, was später einmal kommt. ### Wo die späteren Bereiche stehen @@ -141,13 +141,13 @@ anmeldet, will seine Lage sehen und nicht lesen, was später einmal kommt. Meine Aufgaben, Termine heute und HR-Anträge sind an drei Stellen festgehalten, alle drei für den Einbau gedacht und keine davon auf dem Begrüßungsbildschirm: -1. **`RESERVIERTE_BEREICHE`** in `view-models/dashboard.vm.ts` — die Kacheln als +1. **`RESERVIERTE_BEREICHE`** in `view-models/dashboard.vm.ts`, die Kacheln als Datensatz, mit Titel, Beschreibung, Widget-Domäne und Quell-Feature. 2. **Ein markierter Kommentarblock in `pages/DashboardSeite.tsx`** an genau der - Stelle im Raster, an die sie gehören — mit den konkreten Werten + Stelle im Raster, an die sie gehören, mit den konkreten Werten (`` mit `start={0}`, `{4}`, `{8}`). 3. **Die Bausteingalerie unter `/komponenten`**, Abschnitt „Reservierte - Kacheln" — dort sind sie gestaltet zu sehen. + Kacheln": dort sind sie gestaltet zu sehen. Alle drei sind im Designer-Brief P11 benannt und haben in HiveGrid bereits ihre Widget-Domäne (`tasks`, `schedule`, `hr`). Sie brauchen kein neues Raster, nur @@ -163,9 +163,9 @@ irgendwann fragt jemand, warum die Zahl nie hochzählt. weiterhin auf der Analytics-Übersicht. Das ist Absicht und vorläufig. Nach Abschnitt 3.2 gehört er ins Dashboard. Ihn gleichzeitig aus der Übersicht -zu entfernen, hätte aber 5.1 mitentschieden — die Frage, ob es die -Übersichtsseite überhaupt weiter gibt —, und das ist keine Entscheidung, die -beim Bauen nebenbei fällt. Solange 5.1 offen ist, steht er doppelt. +zu entfernen, hätte aber 5.1 mitentschieden: die Frage, ob es die +Übersichtsseite überhaupt weiter gibt. Das ist keine Entscheidung, die beim +Bauen nebenbei fällt. Solange 5.1 offen ist, steht er doppelt. **Beim Einbau ist das zu bereinigen, nicht zu übernehmen.** Zwei Einstiegsseiten mit derselben Arbeitsliste sind kein Entwurf, sondern ein @@ -175,7 +175,7 @@ Versehen, das sich als Entwurf tarnt. - **Keine Rollenumschaltung.** Gestaltet ist die Sicht der Geschäftsführung. Büro und Monteur entstehen aus denselben Kacheln in anderer Zusammenstellung - (P11) — das ist eine Produktentscheidung, keine Gestaltungsfrage. + (P11): das ist eine Produktentscheidung, keine Gestaltungsfrage. - **Keinen Bearbeitungsmodus.** Die Software hat ihn (`DashboardEditPanel`, Widget-Katalog, gespeichertes Layout). Der Prototyp bildet ihn nicht nach; er zeigt das Ergebnis, nicht das Werkzeug. @@ -200,7 +200,7 @@ Analytics (ein Menüpunkt, Reiter innen) Dashboard (eigener Menüpunkt) Die Kennzahl-Definitionen aus [KPI-KATALOG.md](KPI-KATALOG.md) und die Diagrammregeln aus [DESIGN-SYSTEM.md](DESIGN-SYSTEM.md) gelten für **beide** Features. Ein Umsatzchart im Dashboard rechnet und aussieht wie dasselbe Chart -in Analytics — sonst widersprechen sich zwei Seiten derselben Anwendung. +in Analytics, sonst widersprechen sich zwei Seiten derselben Anwendung. --- @@ -214,13 +214,13 @@ Nicht entschieden. Reihenfolge nach Tragweite: Begrüßungscharakter und wird zur reinen Kennzahlen-Zusammenfassung. - *C:* Sie entfällt; Analytics besteht aus vier fachlichen Seiten. -**5.2 Welche Analytics-Charts werden Dashboard-Widgets? — Vorschlag steht.** +**5.2 Welche Analytics-Charts werden Dashboard-Widgets?: Vorschlag steht.** Gebaut sind vier: Zahlungseingang, Umsatz nach Gewerk, Vertriebstrichter, Auslastung. Der Trichter war der Zweifelsfall (er lebt von der Übergangsquote und wird klein unlesbar); er steht deshalb auf sechs von zwölf Spalten und nicht auf vier. Die Auswahl ist ein Vorschlag zur Abnahme, keine Festlegung. -**5.3 Wo lebt der Handlungsbedarf? — jetzt an beiden Orten.** +**5.3 Wo lebt der Handlungsbedarf?, jetzt an beiden Orten.** Er steht seit dem 31.08. auf dem Dashboard und weiterhin auf der Analytics-Übersicht, weil das Entfernen 5.1 mitentschieden hätte. Siehe Abschnitt 3a. Das ist der dringlichste der offenen Punkte, weil er als @@ -230,7 +230,7 @@ einziger sichtbar doppelt im Repo steht. Globaler Filter wie in Analytics oder pro Widget wie in P11? Die Software hat sich für „pro Widget" entschieden; das ist beim Übertragen zu beachten. -**5.5 Navigation — entschieden am 29.08.2026.** +**5.5 Navigation: entschieden am 29.08.2026.** Analytics ist **ein einzelner Menüpunkt** in der Seitenleiste, gleichrangig neben Dashboard. Die fünf Analyse-Seiten sind darin über Reiter erreichbar, nicht als Unterpunkte in der Navigation. Das Dashboard bleibt als eigener @@ -240,7 +240,7 @@ Offen bleibt daran nur 5.1: Wenn die Übersichtsseite zum Dashboard wird, verliert der Analytics-Bereich seinen ersten Reiter. **5.6 Team-Seite.** -Unabhängig davon offen, weil Zeiterfassung im v2-Backlog steht — siehe +Unabhängig davon offen, weil Zeiterfassung im v2-Backlog steht: siehe [DATENMODELL.md](DATENMODELL.md). --- @@ -248,12 +248,12 @@ Unabhängig davon offen, weil Zeiterfassung im v2-Backlog steht — siehe ## 6. Bis zur Klärung Die Diagrammbausteine, Kennzahl-Definitionen und Regeln gelten unabhängig -davon, wie die beiden Features später geschnitten werden — sie sind von der +davon, wie die beiden Features später geschnitten werden, sie sind von der Frage nicht betroffen. Betroffen ist genau eine Stelle: die Übersichtsseite. Fällt 5.1 auf „sie wird -das Dashboard", dann ist die Arbeit größtenteils getan — der Handlungsbedarf -steht schon dort, die Kennzahlen auch —, und die Übersichtsseite entfällt. +das Dashboard", dann ist die Arbeit größtenteils getan. Der Handlungsbedarf +steht schon dort, die Kennzahlen auch, und die Übersichtsseite entfällt. Fällt sie anders, verliert das Dashboard nichts; die Übersicht behält den Handlungsbedarf und das Dashboard gibt ihn ab. diff --git a/docs/ZIELSYSTEM.md b/docs/ZIELSYSTEM.md index a543c3c..3379164 100644 --- a/docs/ZIELSYSTEM.md +++ b/docs/ZIELSYSTEM.md @@ -11,10 +11,10 @@ Größenordnung: 678 Route-Dateien, davon 575 im Core-Manifest. --- -## 0. Rangfolge beim Einbau — HiveGrid gewinnt +## 0. Rangfolge beim Einbau: HiveGrid gewinnt **Dieser Prototyp ist nachrangig.** Wo er von HiveGrid Cloud abweicht, gilt -HiveGrid — ohne Rückfrage, ohne Ausnahme. Das betrifft alles Globale: +HiveGrid, ohne Rückfrage, ohne Ausnahme. Das betrifft alles Globale: | | Wer bestimmt | |---|---| @@ -29,25 +29,25 @@ Dass dieser Prototyp dieselbe Schrift, dieselbe Seitenleisten-Komponente und dieselben Token benutzt, hat **einen einzigen Zweck**: Er soll neben der Software lesbar sein und nicht wie ein Fremdkörper wirken. Es ist **keine Vorlage, an der sich die Software auszurichten hätte.** Fällt beim Einbau auf, -dass hier ein Wert von HiveGrid abweicht, ist der Wert hier falsch — nicht dort. +dass hier ein Wert von HiveGrid abweicht, ist der Wert hier falsch, nicht dort. ### Was aus diesem Repo verbindlich ist Nur das Fachliche und das Analytics-Eigene: -1. **Die Navigationsstruktur als Verabredung** — zwei Einträge in der +1. **Die Navigationsstruktur als Verabredung**: zwei Einträge in der Seitenleiste (`Dashboard`, `Analytics`), und Analytics trägt eine **innere Leiste** mit den fünf Analyse-Seiten. Verbindlich ist die *Struktur*, nicht ihre Umsetzung hier: In der Software werden diese zwei Einträge in die bestehende `AppSidebar` eingehängt und die innere Leiste über das dortige `SidebarIconsLayout` gebaut. Unser Nachbau ist die Beschreibung, nicht das Bauteil. -2. **Kennzahl-Definitionen** ([KPI-KATALOG.md](KPI-KATALOG.md)) — +2. **Kennzahl-Definitionen** ([KPI-KATALOG.md](KPI-KATALOG.md)), was gerechnet wird, mit welchem Zeitbezug. -3. **Diagrammregeln** ([DESIGN-SYSTEM.md](DESIGN-SYSTEM.md)) — Palette, +3. **Diagrammregeln** ([DESIGN-SYSTEM.md](DESIGN-SYSTEM.md)): Palette, Achsen, Diagrammwahl, Leerzustände. Das ist die Lücke, die HiveGrid heute nicht füllt (siehe [LEITPLANKEN.md](LEITPLANKEN.md) Abschnitt 4). -4. **Verhalten** — Filterlogik, Zeitbezüge, Widget-Sichtbarkeit, +4. **Verhalten**: Filterlogik, Zeitbezüge, Widget-Sichtbarkeit, Sortier- und Blätterverhalten. ### Was aus diesem Repo Gerüst ist und wegfällt @@ -60,7 +60,7 @@ Prototyp alleine lauffähig und beurteilbar ist. Beim Einbau übernehmen der Software. Das **Kachelraster des Dashboards** ist die Ausnahme in dieser Liste: Es ist -kein Gerüst, sondern aus `DashboardPage.tsx` der Software übernommen — +kein Gerüst, sondern aus `DashboardPage.tsx` der Software übernommen, dieselben Klassen, dieselbe Ableitung aus `size.w` und `position.x`. Es fällt nicht weg, es trifft dort auf sein Original. @@ -88,7 +88,7 @@ Fachlich ist das die Phase **P11** (Modul M20): drei feste Rollen-Layouts Komfort-Delta aus **P30** (Edit-Modus, Drilldown, CSV-/Report-Export, Realtime-Opt-out). -**Wichtig:** Dieser Stand ist ausdrücklich **Interim-UI nach AD-28** — der Dev +**Wichtig:** Dieser Stand ist ausdrücklich **Interim-UI nach AD-28**, der Dev baut aus `~/ui` gegen ein stabiles View-Model, damit das Ticket nicht auf den finalen Screen wartet. Der Kommentarkopf von `DashboardPage.tsx` sagt es wörtlich: *„Final Subframe optics = tracked design-nachzug (D-DASH / VD-P30)."* @@ -98,14 +98,14 @@ kein Umbau gegen den Strom. --- -## 2. Gemeinsame Basis — und wo sie auseinanderläuft +## 2. Gemeinsame Basis, und wo sie auseinanderläuft | | Prototyp | HiveGrid Cloud | |---|---|---| -| Subframe-Projekt | `f023064a5ca0` | `f023064a5ca0` — **dasselbe** | +| Subframe-Projekt | `f023064a5ca0` | `f023064a5ca0`: **dasselbe** | | Bibliothek | `ui/`, 86 Komponenten | `apps/web/app/ui/`, Alias `~/ui/*`, 92 Komponenten | | Überschneidung | 82 Komponenten gleich benannt | dieselben 82 | -| Diagramme | Recharts ^2.15.4 | Recharts ^2.15.3 — **dieselbe Bibliothek** | +| Diagramme | Recharts ^2.15.4 | Recharts ^2.15.3: **dieselbe Bibliothek** | | Framework | Next.js 16 | React Router 7 | Die vier Namensunterschiede: `DialogFullscreen` → `FullscreenDialog`, @@ -120,7 +120,7 @@ Grund, warum der Einbau realistisch ein Port ist und keine Neuimplementierung. ## 3. Was beim Einbau konkret anders wird -### 3.1 Daten kommen als View-Model-Prop — bereits umgesetzt +### 3.1 Daten kommen als View-Model-Prop: bereits umgesetzt **Das ist im Prototyp schon so gebaut.** Jede Analyse-Seite ist eine reine Komponente: @@ -177,13 +177,13 @@ Fünf Zustände statt einem. Der Prototyp kennt nur „Daten da"; `loading`, Was der Builder noch **nicht** kennt: `DashboardPageData` führt in der Cloud zusätzlich `activeRole`, `layout`, `generatedAt`, `streamUrl`, `canCustomize`, `liveUpdatesEnabled`, `layoutSource` und `catalog`. Das Dashboard ist dort -rollen- und berechtigungsabhängig — diese Felder kommen beim Einbau dazu. +rollen- und berechtigungsabhängig, diese Felder kommen beim Einbau dazu. ### 3.1a Warum der Prototyp auf Next.js bleibt Die Frage liegt nahe, weil die Software auf React Router 7 läuft. Ein Umbau brächte aber nichts: Im gesamten Prototyp gibt es **vier** Next-spezifische -Importe, alle in zwei Dateien — +Importe, alle in zwei Dateien, | Datei | Import | Schicksal beim Einbau | |---|---|---| @@ -191,19 +191,19 @@ Importe, alle in zwei Dateien — | `app/layout.tsx` | `next`, `next/font/google` | entfällt, Root-Layout gehört der Cloud | Portiert wird nicht die Anwendung, sondern der Ordner -`features/dashboard/{pages,components,view-models,utils}` — und der enthält +`features/dashboard/{pages,components,view-models,utils}`, und der enthält keine Framework-Bindung. React 19, Tailwind v4 und Recharts sind in beiden Repos dieselben. Ein Framework-Wechsel im Prototyp wäre Aufwand ohne Ertrag und würde die Gestaltungsarbeit nur verzögern. -### 3.1b Wo die Analyse in der Navigation landet — offen +### 3.1b Wo die Analyse in der Navigation landet: offen **Die Seitenleiste des Prototyps ist Gerüst, kein Vorschlag.** Sie existiert nur, damit die Seiten einzeln aufrufbar sind, und entfällt beim Einbau (siehe 3.2). Wohin die fünf Analyse-Seiten in der echten Navigation gehören, ist **noch nicht entschieden**. -Der Stand in der Software: Die Seitenleiste hat sechs Gruppen — +Der Stand in der Software: Die Seitenleiste hat sechs Gruppen, Start (Dashboard, Aufgaben) · Kunden · Projekte · Kommunikation · Organisation · Automatisierung. **Eine Analyse-Gruppe gibt es nicht.** Es gibt aber bereits zwei konkurrierende Muster: @@ -211,7 +211,7 @@ zwei konkurrierende Muster: | Muster | Beispiel | Charakter | |---|---|---| | Rollen-Dashboard als Startseite | `/dashboard` (P11/P30) | Widgets, drei Rollen-Layouts, „wie ist meine Lage" | -| Analyse **innerhalb** der Fachdomäne | `leads/analytics` — existiert bereits | vertieft genau eine Domäne | +| Analyse **innerhalb** der Fachdomäne | `leads/analytics`: existiert bereits | vertieft genau eine Domäne | Dieser Prototyp schlägt implizit ein drittes Muster vor: einen **domänenübergreifenden Analysebereich** mit gemeinsamem Zeitraum- und @@ -225,7 +225,7 @@ Dimensionsfilter. (Übersicht → Detail). Finanzen greift über Projekte, Rechnungen und Kontakte hinweg und passt in keine einzelne Domäne. *Dagegen:* eine siebte Gruppe in einer schon langen Seitenleiste. -2. **Verteilt in die Domänen** — Finanzen unter Projekte, Kunden-Analyse unter +2. **Verteilt in die Domänen**: Finanzen unter Projekte, Kunden-Analyse unter Kunden, analog zu `leads/analytics`. *Dafür:* folgt dem bestehenden Muster, keine neue Gruppe. *Dagegen:* Der gemeinsame Zeitraumfilter zerfällt, die Übersichtsseite hat @@ -235,12 +235,12 @@ Dimensionsfilter. Analyse „warum ist das so". Beides in eine Seite zu legen, macht aus dem Einstieg eine Halde. -**Entschieden am 29.08.2026: Option 1**, mit dem Namen **„Analytics"** — der +**Entschieden am 29.08.2026: Option 1**, mit dem Namen **„Analytics"**, der Prototyp setzt das um. Die Seitenleiste spiegelt jetzt die der Software (dieselbe Komponente, dieselben Gruppen); „Analytics" ist ein einzelner Menüpunkt neben „Dashboard", die fünf Seiten sind darin über Reiter erreichbar. -*Ursprüngliche Empfehlung war der Name* **„Statistiken"** — so heißt der +*Ursprüngliche Empfehlung war der Name* **„Statistiken"**: so heißt der Breadcrumb im Prototyp bereits, und „Analyse" ist im Haus durch `leads/analytics` belegt. Das bestehende `/dashboard` bleibt Startseite; unsere Seite „Übersicht" braucht dann einen anderen Namen, sonst konkurrieren zwei @@ -251,14 +251,14 @@ Einstiegsseiten um dieselbe Rolle. | Prototyp | In der Software | |---|---| | „Übersicht" | kollidiert mit der Startseite „Dashboard" | -| „Aufträge" | keine Entität — eine Pipeline-View auf den Projekt-Kern (AD-20) | -| „Kunden" | keine Entität — ein Status am `Kontakt` | +| „Aufträge" | keine Entität, eine Pipeline-View auf den Projekt-Kern (AD-20) | +| „Kunden" | keine Entität, ein Status am `Kontakt` | | „Team" | thematisch unter Organisation/HR; Datenquelle erst in v2 | Das ist eine Produkt- und Designentscheidung, keine Umsetzungsfrage. Sie gehört in die Runde mit dem Head of Design, nicht in den Einbau. -**Nachtrag 29.08.2026:** Die Frage hängt an einer größeren — „Analytics" und +**Nachtrag 29.08.2026:** Die Frage hängt an einer größeren: „Analytics" und „Dashboard" sind zwei Features. Siehe [SCOPE-ANALYTICS-DASHBOARD.md](SCOPE-ANALYTICS-DASHBOARD.md). @@ -267,7 +267,7 @@ in die Runde mit dem Head of Design, nicht in den Einbau. `AppShell.tsx` aus diesem Prototyp fällt beim Einbau **weg**. Die Cloud-Routen laufen bereits in der echten App-Shell mit Sidebar, Tenant-Layout und Breadcrumb (`SubframeAppShell.tsx`, `AppSidebar.tsx`). Screen-Komponenten -dürfen dort ausdrücklich **kein** `~/ui/layouts/DefaultPageLayout` rendern — +dürfen dort ausdrücklich **kein** `~/ui/layouts/DefaultPageLayout` rendern, das bringt eine eigene Beispiel-Sidebar mit und erzeugt eine doppelte Navigation. Stattdessen gilt `PageShell` / `PageHeader` / `PageBody` aus `components/screens/shared/PageShell.tsx`. @@ -278,7 +278,7 @@ Unsere Seitenköpfe und die Filterleiste bleiben, die Rahmen-Navigation nicht. Alle statischen Texte laufen über `react-i18next` (`t("app.dashboard.…")`). Dieser Prototyp hat deutsche Strings fest im JSX. Das ist beim Einbau -mechanische Arbeit, aber flächendeckend — es betrifft jede Karte, jede +mechanische Arbeit, aber flächendeckend, es betrifft jede Karte, jede Achsenbeschriftung und jeden Leerzustand. Die deutschen **Bezeichner im Code** (`umsatz`, `auftraege`) bleiben davon @@ -289,7 +289,7 @@ in P30). In der Cloud sind Charts konsequent `aria-hidden="true"`, und die umgebende Karte liefert eine Textzusammenfassung plus Datentabelle für Screenreader. -Dieser Prototyp hat das **nicht**. Beim Einbau ist es Pflicht — das Repo fährt +Dieser Prototyp hat das **nicht**. Beim Einbau ist es Pflicht, das Repo fährt ein a11y-Lint-Baseline-Gate und axe-Tests je Primitive. ### 3.5 Stabile Oberflächen-IDs @@ -304,7 +304,7 @@ müssen aber auf das dortige Namensschema umgestellt werden. `.planning/INTERIM-UI-DESIGN-STANDARDS.md` schreibt fest: Page-Padding **24**, Card **16**, Grid-Gap **16**, Section-Gap **24**, Field-Gap **16**, Control-Höhe Medium **36**, Input-Radius **4**. Das deckt sich mit dem -8-px-System in [DESIGN-SYSTEM.md](DESIGN-SYSTEM.md) Abschnitt 5 — hier ist +8-px-System in [DESIGN-SYSTEM.md](DESIGN-SYSTEM.md) Abschnitt 5: hier ist nichts anzupassen. --- @@ -318,7 +318,7 @@ Farben direkt im JSX (`fill="#334155"`, `fill="#cbd5e1"`), jedes mit eigenem Gitter (`strokeDasharray="3 3"`), eigener Achsenbreite und eigenem Balkenradius. Es gibt keine geteilte Palette, keine Kategorien-Obergrenze und keine feste Farbzuordnung. `features/dashboard/utils/chartTheme.ts` ist genau -das, was dort fehlt — und der Teil, der sich am ehesten unabhängig vom Rest +das, was dort fehlt, und der Teil, der sich am ehesten unabhängig vom Rest übernehmen lässt. **Ausformulierte Diagramm-Regeln.** [DESIGN-SYSTEM.md](DESIGN-SYSTEM.md) hat in @@ -332,20 +332,20 @@ Definition. --- -## 5. Wer entwirft was — der Rest ist noch nicht fertig designt +## 5. Wer entwirft was, der Rest ist noch nicht fertig designt HiveGrid Cloud ist nach dem **Designer-First-Prinzip** organisiert (`.planning/DESIGNER-FIRST-PLAYBOOK.md`). Der Ablauf ist verbindlich: -1. Dev/Planung stellt je Phase einen **Designer-Brief** bereit — +1. Dev/Planung stellt je Phase einen **Designer-Brief** bereit, *was* das Modul tut und *welche UI-Elemente* vorkommen müssen, **kein Layout**. 2. Der Designer entwirft die Screens in Subframe und darf Spec und UI/UX - **überschreiben** — Anordnung und Layout sind eine Design-Entscheidung. + **überschreiben**: Anordnung und Layout sind eine Design-Entscheidung. 3. Das **Delta** (geänderte Spec-Punkte, neue UX-Entscheidungen, Subframe-Link) wird in den Brief eingetragen. 4. Der Dev setzt um und zieht Spec und Doku nach. -Es gibt 31 solcher Briefs (`.planning/designer-briefs/P01…P34.md`) — Auth, CRM, +Es gibt 31 solcher Briefs (`.planning/designer-briefs/P01…P34.md`): Auth, CRM, Lead-Inbox, Projekt-Pipelines, Automation-Flow-Editor, Form-Builder, Plantafel, Kalender, Telefonie, HR, Billing, Customer-Portal, Help-Center. Für einen großen Teil davon steht der Delta-Block **noch leer**: Der finale Screen ist @@ -357,7 +357,7 @@ noch nicht entworfen, die Route läuft bis dahin auf Interim-UI. Anwendung. Es fügt sich in eine App-Shell und ein Design-System ein, die bereits stehen. - Was hier an Anordnung und Raster festgelegt ist, ist ein **Vorschlag**. Die - Layout-Hoheit liegt beim Designer — der Brief zu P11 sagt ausdrücklich + Layout-Hoheit liegt beim Designer, der Brief zu P11 sagt ausdrücklich „Anordnung = Davids freie Hand". Verbindlich zu übergeben sind die **Kennzahl-Definitionen, die Chart-Regeln und das Verhalten**, nicht die Pixelanordnung. @@ -378,7 +378,7 @@ pnpm dev:local ``` Tenant-App auf `http://app.localhost:3000`. Die lokalen Demo-Zugänge (Tenant -„HiveGrid Demo SHK") stehen im README von HiveGrid Cloud unter „App starten" — +„HiveGrid Demo SHK") stehen im README von HiveGrid Cloud unter „App starten", sie werden hier bewusst nicht wiederholt. Die Demo-Daten sind zunächst ausgeblendet und erscheinen über **„Demo-Daten anzeigen"** oder `?demo=show`. diff --git a/features/dashboard/components/cards/AlertList.tsx b/features/dashboard/components/cards/AlertList.tsx index adfd8ee..60b7a41 100644 --- a/features/dashboard/components/cards/AlertList.tsx +++ b/features/dashboard/components/cards/AlertList.tsx @@ -63,7 +63,7 @@ export function AlertList({ /** * Der Trennstrich sitzt oben, nicht unten. * - * Unten liegend braucht er eine Ausnahme für die letzte Zeile — und + * Unten liegend braucht er eine Ausnahme für die letzte Zeile, und * „die letzte Zeile" gibt es bei zwei Spalten zweimal, einmal je * Spalte, an einer Stelle, die von der Anzahl der Einträge abhängt. * Die rechte Spalte behielt dadurch einen Strich, unter dem nichts @@ -82,10 +82,10 @@ export function AlertList({ >