feat: Dashboard – Donut ohne Überlauf, Achse lesbar, Karten-Optionen
- Budget-Donut: Mittelbetrag passt sich der Länge an (kein Hineinlaufen in den Ring bei 4-stelligen Beträgen) - Vermögensverlauf: Y-Achse ohne Währungssymbol (formatAmount) + etwas mehr linker Rand → „CHF …" wird nicht mehr abgeschnitten - Karten-Optionen: im Anordnen-Modus je Karte einstellbar; Budget-Donut und Budget-Fortschritt können nach Gruppen ODER Kategorien aufschlüsseln (?group_by=), Auswahl wird im Layout (props) mitgespeichert Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -4,7 +4,7 @@ import { api } from "../api";
|
||||
import { useSettings } from "../settings";
|
||||
import IconChip from "../components/IconChip";
|
||||
import Money from "../components/Money";
|
||||
import { formatMoney } from "../format";
|
||||
import { formatMoney, formatAmount } from "../format";
|
||||
import { tokenFarbe } from "./palette";
|
||||
import Donut from "./charts/Donut";
|
||||
import Line from "./charts/Line";
|
||||
@@ -53,9 +53,10 @@ function AccountBalances() {
|
||||
);
|
||||
}
|
||||
|
||||
function BudgetDonut() {
|
||||
function BudgetDonut({ props }) {
|
||||
const { t } = useTranslation();
|
||||
const data = useData(() => api.cardBudgetDonut());
|
||||
const groupBy = props?.group_by || "group";
|
||||
const data = useData(() => api.cardBudgetDonut(groupBy));
|
||||
if (!data) return <Loading />;
|
||||
if (!data.segments?.length) return <div className="dash-empty muted">{t("cards.noBudget")}</div>;
|
||||
const label = data.mode === "planned" ? t("cards.planned") : t("cards.spent");
|
||||
@@ -68,12 +69,17 @@ function NetWorth() {
|
||||
if (!data) return <Loading />;
|
||||
const labels = (data.labels || []).map(shortDate);
|
||||
const serien = [{ name: t("cards.assets"), color: tokenFarbe("--accent", "#3f51b5"), werte: data.values || [] }];
|
||||
return <Line labels={labels} serien={serien} fmt={(v) => formatMoney(v, data.currency)} />;
|
||||
return (
|
||||
<Line labels={labels} serien={serien}
|
||||
fmt={(v) => formatMoney(v, data.currency)}
|
||||
achsenFmt={(v) => formatAmount(v, data.currency)} />
|
||||
);
|
||||
}
|
||||
|
||||
function BudgetProgress() {
|
||||
function BudgetProgress({ props }) {
|
||||
const { t } = useTranslation();
|
||||
const data = useData(() => api.cardBudgetProgress());
|
||||
const groupBy = props?.group_by || "group";
|
||||
const data = useData(() => api.cardBudgetProgress(groupBy));
|
||||
if (!data) return <Loading />;
|
||||
if (!data.rows?.length) return <div className="dash-empty muted">{t("cards.noBudget")}</div>;
|
||||
return (
|
||||
@@ -143,12 +149,22 @@ function RecentTransactions() {
|
||||
);
|
||||
}
|
||||
|
||||
// Registry: Kartentyp -> { Titel-Schlüssel, Komponente, Standardgröße/Mindestgröße }.
|
||||
// Aufschlüsselungs-Option (Gruppen vs. Kategorien) – von Donut und Fortschritt geteilt.
|
||||
const AUFSCHLUESSELUNG = {
|
||||
key: "group_by", labelKey: "cards.breakdown", def: "group",
|
||||
choices: [
|
||||
{ v: "group", labelKey: "cards.byGroup" },
|
||||
{ v: "category", labelKey: "cards.byCategory" },
|
||||
],
|
||||
};
|
||||
|
||||
// Registry: Kartentyp -> { Titel-Schlüssel, Komponente, Standardgröße/Mindestgröße,
|
||||
// optional `options` (im Anordnen-Modus einstellbare Karten-Optionen) }.
|
||||
export const KARTEN = {
|
||||
"account-balances": { titleKey: "cards.balances", Comp: AccountBalances, w: 4, h: 5, minW: 3, minH: 3 },
|
||||
"budget-donut": { titleKey: "cards.budgetDonut", Comp: BudgetDonut, w: 4, h: 5, minW: 3, minH: 4 },
|
||||
"budget-donut": { titleKey: "cards.budgetDonut", Comp: BudgetDonut, w: 4, h: 5, minW: 3, minH: 4, options: [AUFSCHLUESSELUNG] },
|
||||
"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 },
|
||||
"budget-progress": { titleKey: "cards.budgetProgress", Comp: BudgetProgress, w: 4, h: 3, minW: 3, minH: 2, options: [AUFSCHLUESSELUNG] },
|
||||
"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 },
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user