From 7eed5ee6c4ace4f8131490e230d76b51472a804b Mon Sep 17 00:00:00 2001 From: Guido Date: Fri, 21 Aug 2026 09:46:48 +0200 Subject: [PATCH] feat: Ausgaben-Anteile wahlweise als Kreisdiagramm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Neue Karten-Option „Darstellung": Liste (Standard) oder Kreis. Dieselben Zahlen, zwei Lesarten – die Liste nennt jeden Anteil genau, der Kreis zeigt die Verteilung auf einen Blick. Nutzt den vorhandenen Donut, dessen Legende Betrag und Anteil ohnehin schon ausweist. Co-Authored-By: Claude Opus 4.8 --- web/src/dashboard/cards.jsx | 22 +++++++++++++++++++++- web/src/locales/de.json | 5 ++++- web/src/locales/en.json | 5 ++++- 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/web/src/dashboard/cards.jsx b/web/src/dashboard/cards.jsx index 4c41a6c..ed37934 100644 --- a/web/src/dashboard/cards.jsx +++ b/web/src/dashboard/cards.jsx @@ -155,6 +155,16 @@ function ExpenseShare({ props }) { const data = useData(() => api.cardExpenseShare(groupBy)); if (!data) return ; if (!data.rows?.length) return
{t("cards.noExpenses")}
; + // Kreis: der Donut beschriftet seine Legende selbst mit Betrag und Anteil. + if ((props?.darstellung || "liste") === "kreis") { + return ( + ({ name: r.name, value: r.amount, color: r.color }))} + gesamtLabel={t("cards.spent")} + fmt={(v) => formatMoney(v, data.currency)} + /> + ); + } return (
{data.rows.map((r) => { @@ -192,6 +202,16 @@ const AUFSCHLUESSELUNG = { ], }; +// Liste oder Kreis – dieselben Zahlen, zwei Lesarten: die Liste nennt jeden +// Anteil genau, der Kreis zeigt die Verteilung auf einen Blick. +const DARSTELLUNG = { + key: "darstellung", labelKey: "cards.display", def: "liste", + choices: [ + { v: "liste", labelKey: "cards.asList" }, + { v: "kreis", labelKey: "cards.asPie" }, + ], +}; + // Registry: Kartentyp -> { Titel-Schlüssel, Komponente, Standardgröße/Mindestgröße, // optional `options` (im Anordnen-Modus einstellbare Karten-Optionen) }. export const KARTEN = { @@ -200,7 +220,7 @@ export const KARTEN = { "net-worth": { titleKey: "cards.netWorth", Comp: NetWorth, w: 8, h: 4, minW: 4, minH: 3 }, "budget-progress": { titleKey: "cards.budgetProgress", Comp: BudgetProgress, w: 4, h: 3, minW: 3, minH: 2, options: [AUFSCHLUESSELUNG] }, "expense-share": { titleKey: "cards.expenseShare", Comp: ExpenseShare, w: 4, h: 5, minW: 3, minH: 3, - options: [{ ...AUFSCHLUESSELUNG, def: "category" }] }, + options: [{ ...AUFSCHLUESSELUNG, def: "category" }, DARSTELLUNG] }, "income-expense": { titleKey: "cards.incomeExpense", Comp: IncomeExpense, w: 4, h: 2, minW: 2, minH: 2 }, "recent-transactions": { titleKey: "cards.recent", Comp: RecentTransactions, w: 4, h: 4, minW: 3, minH: 3 }, }; diff --git a/web/src/locales/de.json b/web/src/locales/de.json index 39b1bc1..92a2c66 100644 --- a/web/src/locales/de.json +++ b/web/src/locales/de.json @@ -134,7 +134,10 @@ "byGroup": "Gruppen", "byCategory": "Kategorien", "expenseShare": "Ausgaben-Anteile", - "noExpenses": "Noch keine Ausgaben in diesem Monat." + "noExpenses": "Noch keine Ausgaben in diesem Monat.", + "display": "Darstellung", + "asList": "Liste", + "asPie": "Kreis" }, "server": { "unreachable": "Server nicht erreichbar.", diff --git a/web/src/locales/en.json b/web/src/locales/en.json index 9b787cb..56818b1 100644 --- a/web/src/locales/en.json +++ b/web/src/locales/en.json @@ -134,7 +134,10 @@ "byGroup": "Groups", "byCategory": "Categories", "expenseShare": "Expense share", - "noExpenses": "No expenses this month yet." + "noExpenses": "No expenses this month yet.", + "display": "Display", + "asList": "List", + "asPie": "Pie" }, "server": { "unreachable": "Server unreachable.",