import { useParams, useNavigate } from 'react-router-dom';
import { useState } from 'react';
import { useQuery } from '@tanstack/react-query';
import {
Box, Typography, Button, Grid, Card, CardContent,
Table, TableHead, TableBody, TableRow, TableCell,
Chip, Alert, Skeleton, TableContainer, Paper,
IconButton, CircularProgress,
} from '@mui/material';
import { ArrowBack, KeyboardArrowDown, KeyboardArrowUp } from '@mui/icons-material';
import DashboardLayout from '../components/dashboard/DashboardLayout';
import { buchhaltungApi } from '../services/buchhaltung';
import { AUSGABEN_TYP_LABELS } from '../types/buchhaltung.types';
import type { AusgabenTyp, BuchhaltungAudit } 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 }) {
return (
{label}
{fmtEur(Number(spent))}
{budget > 0 && (
Budget: {fmtEur(Number(budget))}
)}
);
}
const AKTION_LABELS: Record = {
erstellt: 'Erstellt',
aktualisiert: 'Aktualisiert',
gebucht: 'Gebucht',
storniert: 'Storniert',
erstellt_wiederkehrend: 'Erstellt (wiederkehrend)',
freigabe_beantragt: 'Freigabe beantragt',
freigabe_genehmigt: 'Freigabe genehmigt',
freigabe_abgelehnt: 'Freigabe abgelehnt',
};
function AuditRows({ transaktionId }: { transaktionId: number }) {
const { data, isLoading } = useQuery({
queryKey: ['buchhaltung-audit', transaktionId],
queryFn: () => buchhaltungApi.getAudit(transaktionId),
});
if (isLoading) {
return (
Lade Verlauf…
);
}
if (!data || data.length === 0) {
return (
Kein Verlauf vorhanden
);
}
return (
<>
{data.map(entry => (
{new Date(entry.erstellt_am).toLocaleString('de-DE')}
{AKTION_LABELS[entry.aktion] ?? entry.aktion}
{entry.erstellt_von ?? '—'}
))}
>
);
}
export default function BuchhaltungKontoDetail() {
const { id } = useParams<{ id: string }>();
const navigate = useNavigate();
const kontoId = Number(id);
const [expandedId, setExpandedId] = useState(null);
const { data, isLoading, isError } = useQuery({
queryKey: ['kontoDetail', kontoId],
queryFn: () => buchhaltungApi.getKontoDetail(kontoId),
enabled: !!kontoId,
});
if (isLoading) return ;
if (isError || !data) return Konto nicht gefunden.;
const { konto, children, transaktionen } = data;
const isEinfach = (konto.budget_typ || 'detailliert') === 'einfach';
const totalEinnahmen = transaktionen
.filter(t => t.typ === 'einnahme' && t.status === 'gebucht')
.reduce((sum, t) => sum + Number(t.betrag), 0);
const totalAusgaben = transaktionen
.filter(t => t.typ === 'ausgabe' && t.status === 'gebucht')
.reduce((sum, t) => sum + Number(t.betrag), 0);
return (
} onClick={() => navigate('/buchhaltung')}>
Zurück
{konto.kontonummer} — {konto.bezeichnung}
{isEinfach ? (
<>
Einnahmen
{fmtEur(totalEinnahmen)}
>
) : (
<>
t.typ === 'ausgabe' && t.status === 'gebucht' && t.ausgaben_typ === 'gwg').reduce((s, t) => s + Number(t.betrag), 0)
} />
t.typ === 'ausgabe' && t.status === 'gebucht' && t.ausgaben_typ === 'anlagen').reduce((s, t) => s + Number(t.betrag), 0)
} />
t.typ === 'ausgabe' && t.status === 'gebucht' && t.ausgaben_typ === 'instandhaltung').reduce((s, t) => s + Number(t.betrag), 0)
} />
Einnahmen
{fmtEur(totalEinnahmen)}
>
)}
{children.length > 0 && (
Unterkonten
Konto
{!isEinfach && Budget GWG}
{!isEinfach && Budget Anlagen}
{!isEinfach && Budget Instandh.}
Budget Gesamt
{children.map(child => {
const childIsEinfach = (child.budget_typ || 'detailliert') === 'einfach';
const childTotal = childIsEinfach
? Number(child.budget_gesamt || 0)
: Number(child.budget_gwg || 0) + Number(child.budget_anlagen || 0) + Number(child.budget_instandhaltung || 0);
return (
navigate(`/buchhaltung/konto/${child.id}`)}
>
{child.kontonummer} — {child.bezeichnung}
{!isEinfach && {childIsEinfach ? '—' : fmtEur(Number(child.budget_gwg))}}
{!isEinfach && {childIsEinfach ? '—' : fmtEur(Number(child.budget_anlagen))}}
{!isEinfach && {childIsEinfach ? '—' : fmtEur(Number(child.budget_instandhaltung))}}
{fmtEur(childTotal)}
);
})}
)}
Transaktionen
Datum
Beschreibung
Typ
Ausgaben-Typ
Betrag
Status
{transaktionen.length === 0 && (
Keine Transaktionen
)}
{transaktionen.map(t => (
<>
setExpandedId(expandedId === t.id ? null : t.id)}>
{expandedId === t.id ? : }
{new Date(t.datum).toLocaleDateString('de-DE')}
{t.beschreibung}
{t.ausgaben_typ ? AUSGABEN_TYP_LABELS[t.ausgaben_typ as AusgabenTyp] : '—'}
{t.typ === 'einnahme' ? '+' : '-'}{fmtEur(Number(t.betrag))}
{t.status}
{expandedId === t.id && }
>
))}
);
}