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
48 lines
1.4 KiB
TypeScript
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>
|
|
);
|
|
}
|