Initial commit: Angular PV Pulse App
This commit is contained in:
100
src/app/features/plant-history/plant-history.component.ts
Normal file
100
src/app/features/plant-history/plant-history.component.ts
Normal file
@@ -0,0 +1,100 @@
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
computed,
|
||||
inject,
|
||||
OnInit,
|
||||
signal,
|
||||
} from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { LiveDataService } from '../../core/services/live-data.service';
|
||||
import { PvHistoryData, PvHistoryEntry } from '../../core/models/pv-data.model';
|
||||
import { LoadingSpinnerComponent, ErrorMessageComponent } from '../../shared';
|
||||
import { DecimalPipe, DatePipe } from '@angular/common';
|
||||
|
||||
type Resolution = 'hour' | 'day' | 'month' | 'year';
|
||||
|
||||
@Component({
|
||||
selector: 'app-plant-history',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [LoadingSpinnerComponent, ErrorMessageComponent, DecimalPipe, DatePipe],
|
||||
templateUrl: './plant-history.component.html',
|
||||
styleUrl: './plant-history.component.scss',
|
||||
})
|
||||
export class PlantHistoryComponent implements OnInit {
|
||||
private readonly route = inject(ActivatedRoute);
|
||||
private readonly liveDataService = inject(LiveDataService);
|
||||
|
||||
readonly resolution = signal<Resolution>('day');
|
||||
readonly historyData = signal<PvHistoryData | null>(null);
|
||||
readonly loading = signal(false);
|
||||
readonly error = signal<string | null>(null);
|
||||
|
||||
readonly resolutions: { value: Resolution; label: string }[] = [
|
||||
{ value: 'hour', label: 'Stündlich' },
|
||||
{ value: 'day', label: 'Täglich' },
|
||||
{ value: 'month', label: 'Monatlich' },
|
||||
{ value: 'year', label: 'Jährlich' },
|
||||
];
|
||||
|
||||
readonly totalEnergy = computed(() =>
|
||||
this.historyData()?.entries.reduce((sum, e) => sum + e.energyKwh, 0) ?? 0
|
||||
);
|
||||
|
||||
readonly peakEntry = computed(() => {
|
||||
const entries = this.historyData()?.entries ?? [];
|
||||
if (!entries.length) return null;
|
||||
return entries.reduce((max, e) => (e.peakPowerKw > max.peakPowerKw ? e : max));
|
||||
});
|
||||
|
||||
readonly chartBarData = computed(() => {
|
||||
const entries = this.historyData()?.entries ?? [];
|
||||
if (!entries.length) return [];
|
||||
const max = Math.max(...entries.map((e) => e.energyKwh));
|
||||
return entries.map((e) => ({
|
||||
...e,
|
||||
barPercent: max > 0 ? (e.energyKwh / max) * 100 : 0,
|
||||
}));
|
||||
});
|
||||
|
||||
private plantId = '';
|
||||
|
||||
ngOnInit(): void {
|
||||
// plantId kommt vom Parent-Route-Snapshot (plant-shell)
|
||||
this.plantId =
|
||||
this.route.parent?.snapshot.paramMap.get('id') ??
|
||||
this.route.snapshot.paramMap.get('id') ??
|
||||
'';
|
||||
this.loadHistory();
|
||||
}
|
||||
|
||||
loadHistory(): void {
|
||||
if (!this.plantId) return;
|
||||
this.loading.set(true);
|
||||
this.error.set(null);
|
||||
this.liveDataService.getHistory(this.plantId, this.resolution()).subscribe({
|
||||
next: (data) => {
|
||||
this.historyData.set(data);
|
||||
this.loading.set(false);
|
||||
},
|
||||
error: () => {
|
||||
this.error.set('Verlaufsdaten konnten nicht geladen werden.');
|
||||
this.loading.set(false);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
setResolution(res: Resolution): void {
|
||||
this.resolution.set(res);
|
||||
this.loadHistory();
|
||||
}
|
||||
|
||||
dateFormat(resolution: Resolution): string {
|
||||
switch (resolution) {
|
||||
case 'hour': return 'dd.MM.yy HH:mm';
|
||||
case 'day': return 'dd.MM.yyyy';
|
||||
case 'month': return 'MMM yyyy';
|
||||
case 'year': return 'yyyy';
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user