"use client"; import React from "react"; import { PageHeader } from "../components/layout/PageHeader"; import { PageContainer } from "../components/layout/PageContainer"; import { KPICard } from "../components/cards/KPICard"; import { ChartCard } from "../components/cards/ChartCard"; import { AlertList } from "../components/cards/AlertList"; import { StatZeile } from "../components/cards/StatZeile"; import { AreaVerlauf } from "../components/charts/AreaVerlauf"; import { BalkenVertikal } from "../components/charts/BalkenVertikal"; import { BalkenHorizontal } from "../components/charts/BalkenHorizontal"; import { Donut } from "../components/charts/Donut"; import { Trichter } from "../components/charts/Trichter"; import { AuslastungsBalken } from "../components/charts/AuslastungsBalken"; import { ChartLeer } from "../components/charts/ChartLeer"; import { ChartLegende } from "../components/charts/ChartLegende"; import { AuftragBadge, RechnungBadge } from "../components/tables/StatusBadge"; import { KATEGORIE_FARBEN, MAX_KATEGORIEN, PRIMAER_FARBE, STATUS_FARBEN, VERGLEICH_FARBE, } from "../utils/chartTheme"; import { formatEuro, formatEuroAchse, formatEuroKompakt, formatProzent, formatZahl, } from "../utils/formatters"; import { DATENSATZ_INFO } from "../data/seed"; /** Beispieldaten, damit die Galerie unabhängig von Filtern immer etwas zeigt. */ const BEISPIEL_REIHE = Array.from({ length: 12 }, (_, i) => ({ datum: `2026-${String(i + 1).padStart(2, "0")}`, label: ["Jan", "Feb", "Mär", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"][i], value: [148, 162, 171, 158, 166, 149, 152, 161, 189, 205, 198, 176][i] * 1000, vergleich: [131, 140, 152, 146, 151, 138, 141, 149, 168, 181, 176, 158][i] * 1000, })); const BEISPIEL_KATEGORIEN = [ { name: "Heizung", value: 842_000 }, { name: "Sanitär", value: 486_000 }, { name: "Photovoltaik", value: 421_000 }, { name: "Klima & Lüftung", value: 268_000 }, { name: "Elektro", value: 194_000 }, { name: "Sonstiges", value: 61_000 }, ]; export function KomponentenSeite() { return ( <>
{KATEGORIE_FARBEN.map((farbe, index) => (
{index + 1}. {farbe}
))}
{Object.entries(STATUS_FARBEN).map(([name, farbe]) => ( Status „{name}“ · {farbe} ))}

Kategorien nutzen die Carbon-Palette, Statusaussagen die Ampelfarben. Beides nie mischen: eine grüne Kategorie neben einem grünen Positiv-Status ist nicht mehr lesbar. Maximal {MAX_KATEGORIEN} Segmente je Chart, der Rest wird zu „Sonstige“ zusammengefasst.

} >
({ label: p.label, value: p.value / 1000 }))} formatWert={(w) => formatZahl(w)} hoehe={200} nurGanzzahlen /> formatZahl(w)} />
Auftrag
Rechnung
    {[ "Nur horizontale Gridlines in #e0e0e0. Vertikale Linien lenken vom Verlauf ab.", "Achsenbeschriftungen 12 px in #525252, keine Tick-Marks, Achsenlinie #8d8d8d.", "Ein Tooltip für alle Charts: dunkle Fläche #393939, weißer Text, kein Doppelpunkt.", "Maximal fünf Kategorien je Chart, alles darüber wird zu „Sonstige“ zusammengefasst.", "Balkenabstand mindestens halbe Balkenbreite; Balken nie breiter als 48 px.", "Zahlen rechtsbündig und in Tabellenziffern, Text linksbündig.", "Karten: 16 px Innenabstand, 16 px Abstand zwischen Karten — innen nie größer als außen.", "Jede Karte braucht einen Leerzustand. Filter können jedes Chart leer laufen lassen.", ].map((regel) => (
  • {regel}
  • ))}
); } function Abschnitt({ titel, text }: { titel: string; text: string }) { return (

{titel}

{text}

); } function Hinweis({ text }: { text: string }) { return (

{text}

); }