feat(overview): add KPI charts to team overview page
Adds three chart.js-backed KPI cards (Kassenstand-Verlauf, Einnahmen & Ausgaben, Top-10 offene Beitraege) to the existing Uebersicht page, consuming the new GET teams/:id/overview/stats endpoint via a new TeamStatsApi service. Introduces a small reusable ChartCanvas shared component that wraps the Chart.js instance lifecycle via @Input()/ ngOnChanges, following this codebase's existing input-decorator convention rather than effect(). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -18,6 +18,89 @@
|
||||
></mat-card
|
||||
>
|
||||
</div>
|
||||
|
||||
<section class="chart-block chart-block--balance">
|
||||
<div class="section-heading">
|
||||
<div>
|
||||
<p class="eyebrow">Kennzahlen</p>
|
||||
<h2>Kassenstand-Verlauf</h2>
|
||||
</div>
|
||||
</div>
|
||||
<mat-card class="chart-card">
|
||||
<mat-card-content>
|
||||
@if (loadingStats()) {
|
||||
<div class="state"><mat-spinner diameter="32" /></div>
|
||||
} @else if (balanceHistory().length === 0) {
|
||||
<div class="state">
|
||||
<mat-icon>show_chart</mat-icon><strong>Noch keine Kassenstand-Historie</strong
|
||||
><span>Sobald Buchungen vorliegen, siehst du den Verlauf hier.</span>
|
||||
</div>
|
||||
} @else {
|
||||
<div class="chart-canvas-box">
|
||||
<app-chart-canvas type="line" [data]="balanceChartData()" [options]="balanceChartOptions" />
|
||||
</div>
|
||||
}
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</section>
|
||||
|
||||
<section class="chart-block chart-block--flow">
|
||||
<div class="section-heading">
|
||||
<div>
|
||||
<p class="eyebrow">Kennzahlen</p>
|
||||
<h2>Einnahmen & Ausgaben</h2>
|
||||
</div>
|
||||
</div>
|
||||
<mat-card class="chart-card">
|
||||
<mat-card-content>
|
||||
@if (loadingStats()) {
|
||||
<div class="state"><mat-spinner diameter="32" /></div>
|
||||
} @else if (monthlyFlow().length === 0) {
|
||||
<div class="state">
|
||||
<mat-icon>bar_chart</mat-icon><strong>Noch keine Bewegungen</strong
|
||||
><span>Einnahmen und Ausgaben erscheinen hier pro Monat.</span>
|
||||
</div>
|
||||
} @else {
|
||||
<div class="chart-canvas-box">
|
||||
<app-chart-canvas type="bar" [data]="flowChartData()" [options]="flowChartOptions" />
|
||||
</div>
|
||||
}
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</section>
|
||||
|
||||
<section class="chart-block chart-block--outstanding">
|
||||
<div class="section-heading">
|
||||
<div>
|
||||
<p class="eyebrow">Kennzahlen</p>
|
||||
<h2>Offene Beiträge (Top 10)</h2>
|
||||
</div>
|
||||
</div>
|
||||
<mat-card class="chart-card">
|
||||
<mat-card-content>
|
||||
@if (loadingStats()) {
|
||||
<div class="state"><mat-spinner diameter="32" /></div>
|
||||
} @else if (topOutstanding().length === 0) {
|
||||
<div class="state">
|
||||
<mat-icon>emoji_events</mat-icon><strong>Keine offenen Beiträge</strong
|
||||
><span>Alle aktiven Mitglieder sind ausgeglichen.</span>
|
||||
</div>
|
||||
} @else {
|
||||
<div class="chart-canvas-box">
|
||||
<app-chart-canvas
|
||||
type="bar"
|
||||
[data]="topOutstandingChartData()"
|
||||
[options]="topOutstandingChartOptions"
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
<a mat-button class="chart-card__link" routerLink="../members"
|
||||
><mat-icon>group</mat-icon>Alle Spieler ansehen</a
|
||||
>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</section>
|
||||
|
||||
<div class="section-heading">
|
||||
<div>
|
||||
<p class="eyebrow">Zuletzt passiert</p>
|
||||
|
||||
Reference in New Issue
Block a user