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 ( {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 && } ))}
); }