Kategorien-Anteile: einstellbare Kategorie-Tiefe (Unterkategorien zusammenfassen)

/dashboard/by-category bekommt depth: rollt jede Artikel-Kategorie auf ihren
Vorfahren der gewuenschten Stufe hoch (1 = oberste Ebene), ohne depth zaehlt
jede zugeordnete Kategorie einzeln (feinste). Neue Karten-Konfig select
Kategorie-Tiefe (Feinste / oberste / bis 2. / bis 3. Stufe). KartenConfig zeigt
jetzt auch bei select den Hinweis.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-07-30 17:39:30 +02:00
parent 1cddb4432c
commit 9b0771ae0e
4 changed files with 48 additions and 8 deletions

View File

@@ -229,7 +229,7 @@ export const api = {
request(`/dashboard/layout/enforced?value=${value ? "true" : "false"}`, { method: "PUT" }),
dashboardStats: () => request("/dashboard/stats"),
dashboardExpirySplit: () => request("/dashboard/expiry-split"),
dashboardByCategory: () => request("/dashboard/by-category"),
dashboardByCategory: (depth) => request(`/dashboard/by-category${depth ? `?depth=${depth}` : ""}`),
dashboardTimeline: (days, productId) =>
request(`/dashboard/timeline?days=${days}${productId ? `&product_id=${productId}` : ""}`),
dashboardActivity: (days) => request(`/dashboard/activity?days=${days}`),

View File

@@ -52,7 +52,7 @@ export default function KartenConfig({
if (f.type === "select") {
return (
<label key={f.key}>
{f.label}
{f.label}{f.hint ? <span className="muted small"> ({f.hint})</span> : null}
<select value={karteProps[f.key] ?? f.default ?? ""}
onChange={(e) => onProps({ [f.key]: e.target.value })}>
{(f.optionen || []).map((o) => <option key={o.value} value={o.value}>{o.label}</option>)}

View File

@@ -463,7 +463,9 @@ function KarteAblaufRing() {
}
function KarteKategorienRing({ props: karteProps }) {
const { daten, fehler } = useDaten(() => api.dashboardByCategory());
// Tiefe: bis zu welcher Kategorie-Stufe zusammengefasst wird (leer = feinste).
const tiefe = karteProps?.tiefe ? Number(karteProps.tiefe) : undefined;
const { daten, fehler } = useDaten(() => api.dashboardByCategory(tiefe), [tiefe]);
if (fehler) return <div className="alert error"><Icon name="alert" size={16} />{fehler}</div>;
if (!daten) return <div className="empty">Lädt…</div>;
@@ -689,7 +691,17 @@ export const KARTEN = {
titel: "Kategorien-Anteile", icon: "tag", vorschau: "ring",
beschreibung: "Ring: welche Kategorie wie viel ausmacht",
standard: { w: 4, h: 6 }, min: { w: 3, h: 5 },
config: [{ key: "detail", type: "boolean", label: "Detailansicht (alle Kategorien einzeln, keine Gruppe Andere)" }],
config: [
{ key: "tiefe", type: "select", label: "Kategorie-Tiefe",
hint: "wie weit Unterkategorien zusammengefasst werden", default: "",
optionen: [
{ value: "", label: "Feinste (jede Kategorie einzeln)" },
{ value: "1", label: "Nur oberste Stufe" },
{ value: "2", label: "Bis 2. Stufe" },
{ value: "3", label: "Bis 3. Stufe" },
] },
{ key: "detail", type: "boolean", label: "Detailansicht (alle Kategorien einzeln, keine Gruppe Andere)" },
],
komponente: KarteKategorienRing,
},
"category-bars": {