feat(buchhaltung): add categories, recurring tx scheduling, sub-pot budget validation, and UX polish
This commit is contained in:
@@ -11,6 +11,8 @@ import { buchhaltungApi } from '../services/buchhaltung';
|
||||
import { AUSGABEN_TYP_LABELS } from '../types/buchhaltung.types';
|
||||
import type { AusgabenTyp } from '../types/buchhaltung.types';
|
||||
|
||||
const fmtEur = (n: number) => new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(n);
|
||||
|
||||
function BudgetCard({ label, budget, spent }: { label: string; budget: number; spent: number }) {
|
||||
const utilization = budget > 0 ? Math.min((spent / budget) * 100, 100) : 0;
|
||||
const over = spent > budget && budget > 0;
|
||||
@@ -18,10 +20,10 @@ function BudgetCard({ label, budget, spent }: { label: string; budget: number; s
|
||||
<Card>
|
||||
<CardContent>
|
||||
<Typography variant="subtitle2" color="text.secondary">{label}</Typography>
|
||||
<Typography variant="h6">{Number(spent).toFixed(2).replace('.', ',')} €</Typography>
|
||||
<Typography variant="h6">{fmtEur(Number(spent))}</Typography>
|
||||
{budget > 0 && (
|
||||
<>
|
||||
<Typography variant="body2" color="text.secondary">Budget: {Number(budget).toFixed(2).replace('.', ',')} €</Typography>
|
||||
<Typography variant="body2" color="text.secondary">Budget: {fmtEur(Number(budget))}</Typography>
|
||||
<LinearProgress
|
||||
variant="determinate"
|
||||
value={utilization}
|
||||
@@ -86,7 +88,7 @@ export default function BuchhaltungKontoDetail() {
|
||||
<Card>
|
||||
<CardContent>
|
||||
<Typography variant="subtitle2" color="text.secondary">Einnahmen</Typography>
|
||||
<Typography variant="h6" color="success.main">{totalEinnahmen.toFixed(2).replace('.', ',')} €</Typography>
|
||||
<Typography variant="h6" color="success.main">{fmtEur(totalEinnahmen)}</Typography>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Grid>
|
||||
@@ -115,11 +117,11 @@ export default function BuchhaltungKontoDetail() {
|
||||
onClick={() => navigate(`/buchhaltung/konto/${child.id}`)}
|
||||
>
|
||||
<TableCell>{child.kontonummer} — {child.bezeichnung}</TableCell>
|
||||
<TableCell align="right">{Number(child.budget_gwg).toFixed(2)} €</TableCell>
|
||||
<TableCell align="right">{Number(child.budget_anlagen).toFixed(2)} €</TableCell>
|
||||
<TableCell align="right">{Number(child.budget_instandhaltung).toFixed(2)} €</TableCell>
|
||||
<TableCell align="right">{fmtEur(Number(child.budget_gwg))}</TableCell>
|
||||
<TableCell align="right">{fmtEur(Number(child.budget_anlagen))}</TableCell>
|
||||
<TableCell align="right">{fmtEur(Number(child.budget_instandhaltung))}</TableCell>
|
||||
<TableCell align="right">
|
||||
{(Number(child.budget_gwg) + Number(child.budget_anlagen) + Number(child.budget_instandhaltung)).toFixed(2)} €
|
||||
{fmtEur(Number(child.budget_gwg) + Number(child.budget_anlagen) + Number(child.budget_instandhaltung))}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
@@ -158,7 +160,7 @@ export default function BuchhaltungKontoDetail() {
|
||||
<TableCell>{t.ausgaben_typ ? AUSGABEN_TYP_LABELS[t.ausgaben_typ as AusgabenTyp] : '—'}</TableCell>
|
||||
<TableCell align="right"
|
||||
sx={{ color: t.typ === 'einnahme' ? 'success.main' : 'error.main' }}>
|
||||
{t.typ === 'einnahme' ? '+' : '-'}{Number(t.betrag).toFixed(2).replace('.', ',')} €
|
||||
{t.typ === 'einnahme' ? '+' : '-'}{fmtEur(Number(t.betrag))}
|
||||
</TableCell>
|
||||
<TableCell>{t.status}</TableCell>
|
||||
</TableRow>
|
||||
|
||||
Reference in New Issue
Block a user