feat(reports): Auswertungen, Kalender, Budgets und Export
Backend: - Gemeinsame Bewegungsschicht flows(), auf der alle Berichte aufbauen; Plan und Ist bleiben dabei getrennt - Forecast, Kategorien mit Drilldown, Abo-Übersicht, Jahresvergleich, Cashflow-Kalender, Budget-Ampel, Sparziel-Fortschritt, gebündeltes Dashboard - Budgetübertrag über Monatsgrenzen, Budgets auf Oberkategorien schließen Unterkategorien ein - Export als CSV (BOM, Semikolon, deutsches Dezimaltrennzeichen) und XLSX mit typisierten Beträgen Frontend: - Dashboard, Cashflow-Kalender mit Bestätigen direkt am Tag, Budget-, Sparziel- und Auswertungsseite - Diagrammpalette gegen beide Flächen auf Kontrast und Farbfehlsichtigkeit geprüft; Grün/Rot als Serienpaar verworfen - Einnahmen/Ausgaben und kumulierter Saldo in getrennten Diagrammen statt auf zwei Größenachsen - Recharts in einen eigenen Chunk ausgelagert 27 neue Backend-Tests (235 gesamt), 16 neue Frontend-Tests (65 gesamt) Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014e7t8UpmoVNMtWivY5LiSH
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* Gemeinsame Bausteine der Diagramme.
|
||||
*
|
||||
* Die Serienfarben stammen aus einer Palette, die gegen die hellen und dunklen
|
||||
* Flächen dieser Anwendung auf Kontrast und Farbfehlsichtigkeit geprüft wurde.
|
||||
* Die Reihenfolge ist Teil dieser Absicherung und darf nicht umsortiert werden.
|
||||
*/
|
||||
|
||||
export const SERIES = {
|
||||
/** Einkünfte, laufendes Jahr, kumulierter Saldo. */
|
||||
one: "var(--viz-series-1)",
|
||||
/** Ausgaben, Vorjahr. */
|
||||
two: "var(--viz-series-2)",
|
||||
three: "var(--viz-series-3)",
|
||||
} as const;
|
||||
|
||||
export const CHROME = {
|
||||
grid: "var(--viz-grid)",
|
||||
axis: "var(--viz-axis)",
|
||||
label: "var(--viz-label)",
|
||||
surface: "var(--viz-surface)",
|
||||
} as const;
|
||||
|
||||
export const STATUS = {
|
||||
good: "var(--viz-good)",
|
||||
warning: "var(--viz-warning)",
|
||||
critical: "var(--viz-critical)",
|
||||
} as const;
|
||||
|
||||
/** Achsen und Raster bleiben zurückhaltend: dünne, durchgezogene Linien. */
|
||||
export const AXIS_PROPS = {
|
||||
stroke: CHROME.axis,
|
||||
tickLine: false,
|
||||
axisLine: false,
|
||||
tick: { fill: CHROME.label, fontSize: 11 },
|
||||
} as const;
|
||||
|
||||
export const GRID_PROPS = {
|
||||
stroke: CHROME.grid,
|
||||
strokeWidth: 1,
|
||||
vertical: false,
|
||||
} as const;
|
||||
|
||||
/** Abgerundete Balkenenden an der Grundlinie. */
|
||||
export const BAR_RADIUS: [number, number, number, number] = [4, 4, 0, 0];
|
||||
|
||||
/** Zwei Pixel Fläche zwischen benachbarten Balken statt eines Rahmens. */
|
||||
export const BAR_GAP = 2;
|
||||
Reference in New Issue
Block a user