Files
dejanandClaude Opus 5 b8bf987d0e feat(dashboard): Analytics-Dashboard als Gestaltungsvorlage zur Übergabe
UI/UX-Prototyp der Analytics-Dashboards in HiveGrid, fachlich auf einen
SHK-/Handwerksbetrieb zugeschnitten. Ziel ist die Übergabe an die Entwicklung,
nicht der Produktivbetrieb.

Inhalt: sechs Seiten (Übersicht, Finanzen, Aufträge, Kunden, Team, Komponenten),
26 KPIs, neun Chart-Bausteine, Filtersystem mit seitenabhängiger Relevanz und ein
deterministischer Demo-Datensatz (420 Kunden, 1.900 Aufträge, Stichtag 30.07.2026).

Drei Quellen sind zusammengeführt: die fachliche Planung mit dem Branchenpartner
(Januar 2026), die Subframe-Komponentenbibliothek aus dem HiveGrid-Pitch und
IBM Carbon Data Visualization für die Diagrammregeln. Herkunft und bewusste
Abweichungen stehen in docs/HERKUNFT.md.

Dokumentation: README, HANDOVER (was echte Logik braucht), docs/DESIGN-SYSTEM,
KPI-KATALOG, DATENMODELL, NAVIGATION, HERKUNFT, ZIELSYSTEM (Einbauort in
HiveGrid Cloud) und LEITPLANKEN (welche Cloud-Screens als Vorbild taugen).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QPeZNwSeU7qG3RRCwaxEZX
2026-08-29 17:25:20 +02:00

48 lines
1.4 KiB
TypeScript

"use client";
import React from "react";
/**
* Miniaturverlauf in KPI-Karten.
* Bewusst als handgeschriebenes SVG: Recharts würde für 8 Punkte
* einen ResponsiveContainer samt Resize-Beobachter aufziehen.
*/
export function Sparkline({ werte, farbe }: { werte: number[]; farbe: string }) {
if (werte.length < 2) return null;
const max = Math.max(...werte);
const min = Math.min(...werte);
const spanne = Math.max(1, max - min);
const punkte = werte
.map((wert, index) => {
const x = (index / (werte.length - 1)) * 100;
const y = 28 - ((wert - min) / spanne) * 24;
return `${x.toFixed(2)},${y.toFixed(2)}`;
})
.join(" ");
const id = `spark-${farbe.replace("#", "")}`;
return (
<svg viewBox="0 0 100 32" className="h-full w-full" preserveAspectRatio="none" aria-hidden="true">
<defs>
<linearGradient id={id} x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stopColor={farbe} stopOpacity="0.22" />
<stop offset="100%" stopColor={farbe} stopOpacity="0" />
</linearGradient>
</defs>
<polygon points={`0,32 ${punkte} 100,32`} fill={`url(#${id})`} />
<polyline
points={punkte}
fill="none"
stroke={farbe}
strokeWidth="1.5"
strokeLinejoin="round"
strokeLinecap="round"
vectorEffect="non-scaling-stroke"
/>
</svg>
);
}