Add: right now card with quik stats
This commit is contained in:
parent
b16d139d35
commit
92b3482110
3 changed files with 171 additions and 2 deletions
|
@ -93,3 +93,90 @@ th {
|
||||||
tr:hover {
|
tr:hover {
|
||||||
background-color: #f5f5f5;
|
background-color: #f5f5f5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Price summary styles - similar to the image */
|
||||||
|
.price-summary {
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
border: 1px solid #e0e0e0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.price-heading {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.price-heading h2 {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
margin: 0;
|
||||||
|
color: #1d5631;
|
||||||
|
}
|
||||||
|
|
||||||
|
.price-subheading {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: #666;
|
||||||
|
margin: 5px 0 15px 0;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.current-price {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.price-label {
|
||||||
|
font-size: 1rem;
|
||||||
|
color: #1d5631;
|
||||||
|
margin-right: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.price-value {
|
||||||
|
font-size: 2rem;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #1d5631;
|
||||||
|
margin-right: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.price-unit {
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.price-change {
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: bold;
|
||||||
|
padding: 2px 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.price-increase {
|
||||||
|
background-color: #ff6b6b;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.price-decrease {
|
||||||
|
background-color: #51cf66;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.price-extremes {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 20px;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: #555;
|
||||||
|
}
|
||||||
|
|
||||||
|
.price-high {
|
||||||
|
color: #e03131;
|
||||||
|
}
|
||||||
|
|
||||||
|
.price-low {
|
||||||
|
color: #2b8a3e;
|
||||||
|
}
|
||||||
|
|
||||||
|
.price-average {
|
||||||
|
color: #555;
|
||||||
|
}
|
||||||
|
|
|
@ -27,6 +27,35 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@if (!loading && !error && priceData.length > 0) {
|
||||||
|
<div class="price-summary">
|
||||||
|
<div class="price-heading">
|
||||||
|
<h2>{{ getRegionName(selectedRegion) }} {{ formattedDisplayDate }}</h2>
|
||||||
|
<p class="price-subheading">(utan moms och andra skatter)</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="current-price">
|
||||||
|
<div class="price-label">Just nu</div>
|
||||||
|
<div class="price-value">{{ currentPrice?.SEK_per_kWh || 0 | number:'1.2-2' }} <span class="price-unit">kr/kWh</span></div>
|
||||||
|
<div class="price-change" [ngClass]="{'price-increase': (currentPrice?.SEK_per_kWh || 0) > averagePrice, 'price-decrease': (currentPrice?.SEK_per_kWh || 0) < averagePrice}">
|
||||||
|
{{ (currentPrice?.SEK_per_kWh || 0) > averagePrice ? '+' : '' }}{{ ((currentPrice?.SEK_per_kWh || 0) - averagePrice) | number:'1.2-2' }}%
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="price-extremes">
|
||||||
|
<div class="price-high">
|
||||||
|
↑ {{ highestPrice?.SEK_per_kWh || 0 | number:'1.2-2' }} kr kl {{ highestPrice?.time_start | date:'HH:mm' }}
|
||||||
|
</div>
|
||||||
|
<div class="price-low">
|
||||||
|
↓ {{ lowestPrice?.SEK_per_kWh || 0 | number:'1.2-2' }} kr kl {{ lowestPrice?.time_start | date:'HH:mm' }}
|
||||||
|
</div>
|
||||||
|
<div class="price-average">
|
||||||
|
{{ averagePrice | number:'1.2-2' }} kr snitt
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
<div class="chart-container">
|
<div class="chart-container">
|
||||||
@if (loading) {
|
@if (loading) {
|
||||||
<div class="loading">
|
<div class="loading">
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Component, OnInit, inject } from '@angular/core';
|
import { Component, OnInit, inject } from '@angular/core';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule, DatePipe } from '@angular/common';
|
||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms';
|
||||||
import { EnergyPriceService, EnergyPrice } from './energy-price.service';
|
import { EnergyPriceService, EnergyPrice } from './energy-price.service';
|
||||||
import { EnergyChartComponent } from './energy-chart/energy-chart.component';
|
import { EnergyChartComponent } from './energy-chart/energy-chart.component';
|
||||||
|
@ -9,7 +9,8 @@ import { EnergyChartComponent } from './energy-chart/energy-chart.component';
|
||||||
templateUrl: './app.component.html',
|
templateUrl: './app.component.html',
|
||||||
styleUrls: ['./app.component.css'],
|
styleUrls: ['./app.component.css'],
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [CommonModule, FormsModule, EnergyChartComponent]
|
imports: [CommonModule, FormsModule, EnergyChartComponent],
|
||||||
|
providers: [DatePipe]
|
||||||
})
|
})
|
||||||
export class AppComponent implements OnInit {
|
export class AppComponent implements OnInit {
|
||||||
title = 'Energy Price Dashboard';
|
title = 'Energy Price Dashboard';
|
||||||
|
@ -30,6 +31,7 @@ export class AppComponent implements OnInit {
|
||||||
selectedRegion = this.regions[Math.floor(Math.random() * this.regions.length)].value;
|
selectedRegion = this.regions[Math.floor(Math.random() * this.regions.length)].value;
|
||||||
|
|
||||||
private energyPriceService = inject(EnergyPriceService);
|
private energyPriceService = inject(EnergyPriceService);
|
||||||
|
private datePipe = inject(DatePipe);
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
// Load saved region from localStorage if available
|
// Load saved region from localStorage if available
|
||||||
|
@ -84,4 +86,55 @@ export class AppComponent implements OnInit {
|
||||||
get formattedDate(): string {
|
get formattedDate(): string {
|
||||||
return this.selectedDate.toISOString().split('T')[0];
|
return this.selectedDate.toISOString().split('T')[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get formattedDisplayDate(): string {
|
||||||
|
return this.datePipe.transform(this.selectedDate, 'd MMMM yyyy') || '';
|
||||||
|
}
|
||||||
|
|
||||||
|
get currentPrice(): EnergyPrice | null {
|
||||||
|
if (!this.priceData || this.priceData.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const now = new Date();
|
||||||
|
const currentHour = now.getHours();
|
||||||
|
|
||||||
|
// Find the price for the current hour
|
||||||
|
return this.priceData.find(price => {
|
||||||
|
const priceHour = new Date(price.time_start).getHours();
|
||||||
|
return priceHour === currentHour;
|
||||||
|
}) || this.priceData[0]; // Default to first price if not found
|
||||||
|
}
|
||||||
|
|
||||||
|
get averagePrice(): number {
|
||||||
|
if (!this.priceData || this.priceData.length === 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const sum = this.priceData.reduce((total, price) => total + price.SEK_per_kWh, 0);
|
||||||
|
return sum / this.priceData.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
get highestPrice(): EnergyPrice | null {
|
||||||
|
if (!this.priceData || this.priceData.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.priceData.reduce((max, price) =>
|
||||||
|
price.SEK_per_kWh > max.SEK_per_kWh ? price : max, this.priceData[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
get lowestPrice(): EnergyPrice | null {
|
||||||
|
if (!this.priceData || this.priceData.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.priceData.reduce((min, price) =>
|
||||||
|
price.SEK_per_kWh < min.SEK_per_kWh ? price : min, this.priceData[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
getRegionName(regionCode: string): string {
|
||||||
|
const region = this.regions.find(r => r.value === regionCode);
|
||||||
|
return region ? region.label : regionCode;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue