diff --git a/frontend/src/pages/BuchhaltungKontoDetail.tsx b/frontend/src/pages/BuchhaltungKontoDetail.tsx index b942a21..7b852ee 100644 --- a/frontend/src/pages/BuchhaltungKontoDetail.tsx +++ b/frontend/src/pages/BuchhaltungKontoDetail.tsx @@ -1,15 +1,17 @@ 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, LinearProgress, Chip, Alert, Skeleton, TableContainer, Paper, + IconButton, CircularProgress, } from '@mui/material'; -import { ArrowBack } from '@mui/icons-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 } 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); @@ -37,10 +39,77 @@ function BudgetCard({ label, budget, spent }: { label: string; budget: number; s ); } +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], @@ -163,6 +232,7 @@ export default function BuchhaltungKontoDetail() { + Datum Beschreibung Typ @@ -173,23 +243,32 @@ export default function BuchhaltungKontoDetail() { {transaktionen.length === 0 && ( - Keine Transaktionen + Keine Transaktionen )} {transaktionen.map(t => ( - - {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} - + <> + 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 && } + ))}