feat: Kategorie als eigene Spalte in der Buchungsliste
Die Auswahl sass unter dem Buchungstext. Damit wurden die Zeilen unterschiedlich hoch, die Spalte franste aus, und vergleichen liess sich nichts – genau das, wofuer eine Tabelle da ist. Jetzt zwei Spalten: 'Buchung' mit dem Text und darunter dem Verwendungszweck, 'Kategorie' mit der Auswahl. Ein Uebertrag zeigt dort einen Strich – er ordnet kein Geld ein, er verschiebt es. Die Spaltenliste hat sich damit geaendert, deshalb eine neue Kennung fuer die Tabelle: Die gespeicherte Reihenfolge kennt die neue Spalte nicht und haette die Textspalte ans Ende geschoben. Einmalig sind damit Breiten und Filter dieser Tabelle zurueckgesetzt. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+5
-13
@@ -1308,18 +1308,10 @@ tr.row-dup {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Kategorie-Auswahl in einer Tabellenzeile. Sie steht dort, wo bisher nur der
|
/* Kategorie-Auswahl in einer Tabellenzeile: eigene Spalte, also volle
|
||||||
Name der Kategorie stand – also klein und gedeckelt, nicht über die ganze
|
Zellenbreite – aber ohne den Abstand, den sie im Formular unter ihrer
|
||||||
(wachsende) Spalte. */
|
Beschriftung braucht. Der verschöbe sie gegen die übrigen Zellen. */
|
||||||
.zeilen-kategorie {
|
.datatable td .catsel-btn {
|
||||||
max-width: 240px;
|
|
||||||
margin-top: 2px;
|
|
||||||
}
|
|
||||||
.zeilen-kategorie .catsel-btn {
|
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
padding: 3px 6px;
|
padding: 4px 8px;
|
||||||
font-size: 0.8rem;
|
|
||||||
}
|
|
||||||
.zeilen-kategorie .catsel-value {
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -253,7 +253,8 @@
|
|||||||
"amountRequired": "Bitte einen Betrag eingeben.",
|
"amountRequired": "Bitte einen Betrag eingeben.",
|
||||||
"accountRequired": "Bitte ein Konto wählen.",
|
"accountRequired": "Bitte ein Konto wählen.",
|
||||||
"budgetAsSavings": "Als Sparen ins Budget zählen",
|
"budgetAsSavings": "Als Sparen ins Budget zählen",
|
||||||
"budgetCategory": "Budget-Kategorie"
|
"budgetCategory": "Budget-Kategorie",
|
||||||
|
"subject": "Buchung"
|
||||||
},
|
},
|
||||||
"budget": {
|
"budget": {
|
||||||
"title": "Budget",
|
"title": "Budget",
|
||||||
|
|||||||
@@ -253,7 +253,8 @@
|
|||||||
"amountRequired": "Please enter an amount.",
|
"amountRequired": "Please enter an amount.",
|
||||||
"accountRequired": "Please choose an account.",
|
"accountRequired": "Please choose an account.",
|
||||||
"budgetAsSavings": "Count as savings in the budget",
|
"budgetAsSavings": "Count as savings in the budget",
|
||||||
"budgetCategory": "Budget category"
|
"budgetCategory": "Budget category",
|
||||||
|
"subject": "Subject"
|
||||||
},
|
},
|
||||||
"budget": {
|
"budget": {
|
||||||
"title": "Budget",
|
"title": "Budget",
|
||||||
|
|||||||
@@ -234,7 +234,10 @@ export default function Transactions() {
|
|||||||
icon: cat?.icon || "more-horizontal",
|
icon: cat?.icon || "more-horizontal",
|
||||||
color: cat?.color || "#6b7480",
|
color: cat?.color || "#6b7480",
|
||||||
title: zweck || cat?.name || t("transactions.uncategorized"),
|
title: zweck || cat?.name || t("transactions.uncategorized"),
|
||||||
sub: zweck ? (cat?.name || t("transactions.uncategorized")) : "",
|
// Der Verwendungszweck, falls er neben dem Empfänger noch etwas sagt.
|
||||||
|
// Die Kategorie steht in ihrer eigenen Spalte.
|
||||||
|
sub: tx.payee && tx.description && tx.description !== tx.payee
|
||||||
|
? tx.description : "",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -245,7 +248,8 @@ export default function Transactions() {
|
|||||||
render: (tx) => <span className="nowrap">{formatDate(tx.date)}</span>,
|
render: (tx) => <span className="nowrap">{formatDate(tx.date)}</span>,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "category", header: t("transactions.category"), grow: true, min: 200,
|
// Wofür die Zahlung war – danach sucht man in der Liste.
|
||||||
|
key: "text", header: t("transactions.subject"), grow: true, min: 220,
|
||||||
filterText: (tx) => rowLabel(tx).title,
|
filterText: (tx) => rowLabel(tx).title,
|
||||||
sortValue: (tx) => rowLabel(tx).title,
|
sortValue: (tx) => rowLabel(tx).title,
|
||||||
render: (tx) => {
|
render: (tx) => {
|
||||||
@@ -255,21 +259,7 @@ export default function Transactions() {
|
|||||||
<IconChip name={l.icon} color={l.color} size={26} />
|
<IconChip name={l.icon} color={l.color} size={26} />
|
||||||
<div className="named-text">
|
<div className="named-text">
|
||||||
<div className="ellipsis">{l.title}</div>
|
<div className="ellipsis">{l.title}</div>
|
||||||
{/* Die Kategorie direkt in der Zeile ändern – dafür musste man
|
{l.sub && <div className="named-sub ellipsis">{l.sub}</div>}
|
||||||
vorher jede Buchung einzeln zum Bearbeiten öffnen. Ein
|
|
||||||
Übertrag bekommt keine, dort bleibt der Text stehen. */}
|
|
||||||
{tx.type === "transfer" ? (
|
|
||||||
l.sub && <div className="named-sub ellipsis">{l.sub}</div>
|
|
||||||
) : (
|
|
||||||
<div className="zeilen-kategorie">
|
|
||||||
<CategorySelect
|
|
||||||
groups={tx.type === "income" ? incomeGroups : expenseGroups}
|
|
||||||
value={tx.category_id}
|
|
||||||
onChange={(id) => kategorieSetzen(tx, id)}
|
|
||||||
placeholder={t("transactions.uncategorized")}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{/* Verknüpft heisst: zählt nicht als Ausgabe oder Einnahme.
|
{/* Verknüpft heisst: zählt nicht als Ausgabe oder Einnahme.
|
||||||
Ohne das Gegenkonto sagt „Übertrag" nichts. */}
|
Ohne das Gegenkonto sagt „Übertrag" nichts. */}
|
||||||
{links[String(tx.id)] && (
|
{links[String(tx.id)] && (
|
||||||
@@ -284,6 +274,26 @@ export default function Transactions() {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
// Eigene Spalte, damit die Auswahl in der Zeile steht und nicht unter dem
|
||||||
|
// Text – gestapelt wurden die Zeilen hoch und die Spalte ausgefranst.
|
||||||
|
key: "category", header: t("transactions.category"), width: 210,
|
||||||
|
filterText: (tx) => (tx.category_id ? categoryById[tx.category_id]?.name : "") || "",
|
||||||
|
sortValue: (tx) => (tx.category_id ? categoryById[tx.category_id]?.name : "") || "",
|
||||||
|
render: (tx) => (
|
||||||
|
// Ein Übertrag bekommt keine Kategorie – er ordnet kein Geld ein.
|
||||||
|
tx.type === "transfer" ? (
|
||||||
|
<span className="muted">—</span>
|
||||||
|
) : (
|
||||||
|
<CategorySelect
|
||||||
|
groups={tx.type === "income" ? incomeGroups : expenseGroups}
|
||||||
|
value={tx.category_id}
|
||||||
|
onChange={(id) => kategorieSetzen(tx, id)}
|
||||||
|
placeholder={t("transactions.uncategorized")}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: "account", header: t("transactions.account"), width: 150,
|
key: "account", header: t("transactions.account"), width: 150,
|
||||||
filterText: (tx) => accountById[tx.account_id]?.name || "",
|
filterText: (tx) => accountById[tx.account_id]?.name || "",
|
||||||
@@ -353,7 +363,7 @@ export default function Transactions() {
|
|||||||
|
|
||||||
<div className="card">
|
<div className="card">
|
||||||
<DataTable
|
<DataTable
|
||||||
id="transactions"
|
id="transactions-v2"
|
||||||
rows={txns}
|
rows={txns}
|
||||||
getRowKey={(tx) => tx.id}
|
getRowKey={(tx) => tx.id}
|
||||||
empty={t("transactions.empty")}
|
empty={t("transactions.empty")}
|
||||||
|
|||||||
Reference in New Issue
Block a user