diff --git a/src/app/app.component.css b/src/app/app.component.css
index 81ada23..e69de29 100644
--- a/src/app/app.component.css
+++ b/src/app/app.component.css
@@ -1,173 +0,0 @@
-.container {
- max-width: 1200px;
- margin: 0 auto;
- padding: 20px;
- font-family: Arial, sans-serif;
-}
-
-.controls {
- display: flex;
- justify-content: space-between;
- margin-bottom: 20px;
- flex-wrap: wrap;
- gap: 10px;
-}
-
-.form-group {
- margin-bottom: 10px;
- flex: 1;
- min-width: 200px;
-}
-
-label {
- display: block;
- margin-bottom: 5px;
- font-weight: bold;
-}
-
-/* Fixed height for input/select elements */
-select, input {
- width: 100%;
- padding: 8px;
- border: 1px solid #ccc;
- border-radius: 4px;
- box-sizing: border-box;
- height: 40px; /* Set a fixed height for both */
- line-height: 24px; /* Consistent line height */
- font-size: 14px; /* Consistent font size */
- appearance: auto; /* Preserve native appearance but ensure consistent sizing */
-}
-
-.date-input {
- width: 100%;
- max-width: 100%;
-}
-
-.chart-container {
- background-color: #f9f9f9;
- border-radius: 8px;
- padding: 20px;
- min-height: 400px;
- margin-bottom: 20px;
-}
-
-.loading, .error {
- display: flex;
- justify-content: center;
- align-items: center;
- height: 400px;
-}
-
-.error {
- color: #d9534f;
-}
-
-.price-list {
- margin-top: 30px;
-}
-
-table {
- width: 100%;
- border-collapse: collapse;
-}
-
-th, td {
- padding: 10px;
- text-align: left;
- border-bottom: 1px solid #ddd;
-}
-
-th {
- background-color: #f2f2f2;
-}
-
-tr:hover {
- 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;
-}
diff --git a/src/app/app.component.html b/src/app/app.component.html
index edddf25..95cc6cb 100644
--- a/src/app/app.component.html
+++ b/src/app/app.component.html
@@ -1,100 +1,7 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- @if (!loading && !error && priceData.length > 0) {
-
-
-
{{ getRegionName(selectedRegion) }} {{ formattedDisplayDate }}
-
(utan moms och andra skatter)
-
-
-
-
Just nu
-
{{ currentPrice?.SEK_per_kWh || 0 | number:'1.2-2' }} kr/kWh
-
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' }}%
-
-
-
-
-
- ↑ {{ highestPrice?.SEK_per_kWh || 0 | number:'1.2-2' }} kr kl {{ highestPrice?.time_start | date:'HH:mm' }}
-
-
- ↓ {{ lowestPrice?.SEK_per_kWh || 0 | number:'1.2-2' }} kr kl {{ lowestPrice?.time_start | date:'HH:mm' }}
-
-
- {{ averagePrice | number:'1.2-2' }} kr snitt
-
-
-
- }
-
-
- @if (loading) {
-
-
Loading energy price data...
-
- }
-
- @if (error) {
-
- }
-
- @if (!loading && !error) {
-
- }
-
-
- @if (!loading && !error && priceData.length > 0) {
-
-
Hour-by-hour prices
-
-
-
- Time |
- SEK/kWh |
- EUR/kWh |
-
-
-
- @for (price of priceData; track price.time_start) {
-
- {{ price.time_start | date:'HH:00' }} - {{ price.time_end | date:'HH:00' }} |
- {{ price.SEK_per_kWh | number:'1.2-4' }} |
- {{ price.EUR_per_kWh | number:'1.2-4' }} |
-
- }
-
-
-
- }
+
diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index 63cf7e4..fd1c593 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -1,140 +1,16 @@
-import { Component, OnInit, inject } from '@angular/core';
-import { CommonModule, DatePipe } from '@angular/common';
-import { FormsModule } from '@angular/forms';
-import { EnergyPriceService, EnergyPrice } from './energy-price.service';
-import { EnergyChartComponent } from './energy-chart/energy-chart.component';
+import { Component } from '@angular/core';
+import { provideRouter } from '@angular/router';
+import { HeaderComponent } from './components/header/header.component';
+import { FooterComponent } from './components/footer/footer.component';
+import { RouterOutlet } from '@angular/router';
@Component({
selector: 'app-root',
- templateUrl: './app.component.html',
- styleUrls: ['./app.component.css'],
standalone: true,
- imports: [CommonModule, FormsModule, EnergyChartComponent],
- providers: [DatePipe]
+ imports: [HeaderComponent, FooterComponent, RouterOutlet],
+ templateUrl: './app.component.html',
+ styleUrls: ['./app.component.css']
})
-export class AppComponent implements OnInit {
+export class AppComponent {
title = 'Energy Price Dashboard';
- priceData: EnergyPrice[] = [];
- loading = true;
- error = '';
-
- regions = [
- { value: 'SE1', label: 'Luleå / Norra Sverige' },
- { value: 'SE2', label: 'Sundsvall / Norra Mellansverige' },
- { value: 'SE3', label: 'Stockholm / Södra Mellansverige' },
- { value: 'SE4', label: 'Malmö / Södra Sverige' }
- ];
-
- // Default values
- selectedDate = new Date();
- // Default will be overridden by localStorage if available
- selectedRegion = this.regions[Math.floor(Math.random() * this.regions.length)].value;
-
- private energyPriceService = inject(EnergyPriceService);
- private datePipe = inject(DatePipe);
-
- ngOnInit() {
- // Load saved region from localStorage if available
- const savedRegion = localStorage.getItem('selectedRegion');
- if (savedRegion) {
- this.selectedRegion = savedRegion;
- }
-
- this.loadPriceData();
- }
-
- loadPriceData() {
- this.loading = true;
- this.error = '';
-
- const { year, month, day } = this.energyPriceService.formatDate(this.selectedDate);
-
- this.energyPriceService.getPrices(year, month, day, this.selectedRegion)
- .subscribe({
- next: (data) => {
- this.priceData = data;
- this.loading = false;
- },
- error: (err) => {
- this.error = 'Failed to load energy price data. Please try again later.';
- this.loading = false;
- console.error('Error fetching price data:', err);
- }
- });
- }
-
- onRegionChange() {
- // Save selected region to localStorage
- localStorage.setItem('selectedRegion', this.selectedRegion);
- this.loadPriceData();
- }
-
- onDateChange(event: Event) {
- // Fix: properly handle date input event
- const inputElement = event.target as HTMLInputElement;
- if (inputElement.value) {
- this.selectedDate = new Date(inputElement.value);
- this.loadPriceData();
- }
- }
-
- get maxDate(): string {
- const today = new Date();
- return today.toISOString().split('T')[0];
- }
-
- get formattedDate(): string {
- 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;
- }
}
diff --git a/src/app/app.config.ts b/src/app/app.config.ts
index 6896639..e475f53 100644
--- a/src/app/app.config.ts
+++ b/src/app/app.config.ts
@@ -2,8 +2,15 @@ import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
import { provideRouter } from '@angular/router';
import { routes } from './app.routes';
+
+import { provideHttpClient } from '@angular/common/http';
import { provideCharts, withDefaultRegisterables } from 'ng2-charts';
export const appConfig: ApplicationConfig = {
- providers: [provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes), provideCharts(withDefaultRegisterables())]
+ providers: [
+ provideZoneChangeDetection({ eventCoalescing: true }),
+ provideRouter(routes),
+ provideCharts(withDefaultRegisterables()),
+ provideHttpClient(),
+ ]
};
diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts
index dc39edb..afc6859 100644
--- a/src/app/app.routes.ts
+++ b/src/app/app.routes.ts
@@ -1,3 +1,7 @@
import { Routes } from '@angular/router';
+import { HomeComponent } from './pages/home/home.component';
-export const routes: Routes = [];
+export const routes: Routes = [
+ { path: '', component: HomeComponent },
+ { path: '**', redirectTo: '' }
+];
diff --git a/src/app/energy-chart/energy-chart.component.css b/src/app/components/energy-chart/energy-chart.component.css
similarity index 100%
rename from src/app/energy-chart/energy-chart.component.css
rename to src/app/components/energy-chart/energy-chart.component.css
diff --git a/src/app/energy-chart/energy-chart.component.html b/src/app/components/energy-chart/energy-chart.component.html
similarity index 100%
rename from src/app/energy-chart/energy-chart.component.html
rename to src/app/components/energy-chart/energy-chart.component.html
diff --git a/src/app/energy-chart/energy-chart.component.ts b/src/app/components/energy-chart/energy-chart.component.ts
similarity index 97%
rename from src/app/energy-chart/energy-chart.component.ts
rename to src/app/components/energy-chart/energy-chart.component.ts
index dc9849e..7655210 100644
--- a/src/app/energy-chart/energy-chart.component.ts
+++ b/src/app/components/energy-chart/energy-chart.component.ts
@@ -2,7 +2,7 @@ import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ChartConfiguration, ChartData, ChartType } from 'chart.js';
import { BaseChartDirective } from 'ng2-charts';
-import { EnergyPrice } from '../energy-price.service';
+import { EnergyPrice } from '../../services/energy-price.service';
@Component({
selector: 'app-energy-chart',
diff --git a/src/app/components/footer/footer.component.html b/src/app/components/footer/footer.component.html
new file mode 100644
index 0000000..8829ba6
--- /dev/null
+++ b/src/app/components/footer/footer.component.html
@@ -0,0 +1,73 @@
+
diff --git a/src/app/components/footer/footer.component.ts b/src/app/components/footer/footer.component.ts
new file mode 100644
index 0000000..1996691
--- /dev/null
+++ b/src/app/components/footer/footer.component.ts
@@ -0,0 +1,13 @@
+import { Component } from '@angular/core';
+import { RouterModule, RouterLink } from '@angular/router';
+import { CommonModule } from '@angular/common';
+
+@Component({
+ selector: 'app-footer',
+ standalone: true,
+ imports: [RouterModule, RouterLink, CommonModule],
+ templateUrl: './footer.component.html'
+})
+export class FooterComponent {
+ currentYear = new Date().getFullYear();
+}
diff --git a/src/app/components/header/header.component.html b/src/app/components/header/header.component.html
new file mode 100644
index 0000000..85a53b8
--- /dev/null
+++ b/src/app/components/header/header.component.html
@@ -0,0 +1,34 @@
+
diff --git a/src/app/components/header/header.component.ts b/src/app/components/header/header.component.ts
new file mode 100644
index 0000000..5086c29
--- /dev/null
+++ b/src/app/components/header/header.component.ts
@@ -0,0 +1,17 @@
+import { Component } from '@angular/core';
+import { RouterModule, RouterLink, RouterLinkActive } from '@angular/router';
+import { CommonModule } from '@angular/common';
+
+@Component({
+ selector: 'app-header',
+ standalone: true,
+ imports: [RouterModule, RouterLink, RouterLinkActive, CommonModule],
+ templateUrl: './header.component.html'
+})
+export class HeaderComponent {
+ isMenuOpen = false;
+
+ toggleMenu() {
+ this.isMenuOpen = !this.isMenuOpen;
+ }
+}
diff --git a/src/app/pages/home/home.component.css b/src/app/pages/home/home.component.css
new file mode 100644
index 0000000..81ada23
--- /dev/null
+++ b/src/app/pages/home/home.component.css
@@ -0,0 +1,173 @@
+.container {
+ max-width: 1200px;
+ margin: 0 auto;
+ padding: 20px;
+ font-family: Arial, sans-serif;
+}
+
+.controls {
+ display: flex;
+ justify-content: space-between;
+ margin-bottom: 20px;
+ flex-wrap: wrap;
+ gap: 10px;
+}
+
+.form-group {
+ margin-bottom: 10px;
+ flex: 1;
+ min-width: 200px;
+}
+
+label {
+ display: block;
+ margin-bottom: 5px;
+ font-weight: bold;
+}
+
+/* Fixed height for input/select elements */
+select, input {
+ width: 100%;
+ padding: 8px;
+ border: 1px solid #ccc;
+ border-radius: 4px;
+ box-sizing: border-box;
+ height: 40px; /* Set a fixed height for both */
+ line-height: 24px; /* Consistent line height */
+ font-size: 14px; /* Consistent font size */
+ appearance: auto; /* Preserve native appearance but ensure consistent sizing */
+}
+
+.date-input {
+ width: 100%;
+ max-width: 100%;
+}
+
+.chart-container {
+ background-color: #f9f9f9;
+ border-radius: 8px;
+ padding: 20px;
+ min-height: 400px;
+ margin-bottom: 20px;
+}
+
+.loading, .error {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 400px;
+}
+
+.error {
+ color: #d9534f;
+}
+
+.price-list {
+ margin-top: 30px;
+}
+
+table {
+ width: 100%;
+ border-collapse: collapse;
+}
+
+th, td {
+ padding: 10px;
+ text-align: left;
+ border-bottom: 1px solid #ddd;
+}
+
+th {
+ background-color: #f2f2f2;
+}
+
+tr:hover {
+ 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;
+}
diff --git a/src/app/pages/home/home.component.html b/src/app/pages/home/home.component.html
new file mode 100644
index 0000000..edddf25
--- /dev/null
+++ b/src/app/pages/home/home.component.html
@@ -0,0 +1,100 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ @if (!loading && !error && priceData.length > 0) {
+
+
+
{{ getRegionName(selectedRegion) }} {{ formattedDisplayDate }}
+
(utan moms och andra skatter)
+
+
+
+
Just nu
+
{{ currentPrice?.SEK_per_kWh || 0 | number:'1.2-2' }} kr/kWh
+
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' }}%
+
+
+
+
+
+ ↑ {{ highestPrice?.SEK_per_kWh || 0 | number:'1.2-2' }} kr kl {{ highestPrice?.time_start | date:'HH:mm' }}
+
+
+ ↓ {{ lowestPrice?.SEK_per_kWh || 0 | number:'1.2-2' }} kr kl {{ lowestPrice?.time_start | date:'HH:mm' }}
+
+
+ {{ averagePrice | number:'1.2-2' }} kr snitt
+
+
+
+ }
+
+
+ @if (loading) {
+
+
Loading energy price data...
+
+ }
+
+ @if (error) {
+
+ }
+
+ @if (!loading && !error) {
+
+ }
+
+
+ @if (!loading && !error && priceData.length > 0) {
+
+
Hour-by-hour prices
+
+
+
+ Time |
+ SEK/kWh |
+ EUR/kWh |
+
+
+
+ @for (price of priceData; track price.time_start) {
+
+ {{ price.time_start | date:'HH:00' }} - {{ price.time_end | date:'HH:00' }} |
+ {{ price.SEK_per_kWh | number:'1.2-4' }} |
+ {{ price.EUR_per_kWh | number:'1.2-4' }} |
+
+ }
+
+
+
+ }
+
diff --git a/src/app/pages/home/home.component.ts b/src/app/pages/home/home.component.ts
new file mode 100644
index 0000000..52f748a
--- /dev/null
+++ b/src/app/pages/home/home.component.ts
@@ -0,0 +1,144 @@
+import { Component, OnInit, inject } from '@angular/core';
+import { CommonModule, DatePipe } from '@angular/common';
+import { FormsModule } from '@angular/forms';
+import { EnergyPriceService, EnergyPrice } from '../../services/energy-price.service';
+import { EnergyChartComponent } from '../../components/energy-chart/energy-chart.component';
+
+@Component({
+ selector: 'app-home',
+ templateUrl: './home.component.html',
+ styleUrls: ['./home.component.css'],
+ standalone: true,
+ imports: [
+ CommonModule,
+ FormsModule,
+ EnergyChartComponent,
+ ],
+ providers: [DatePipe]
+})
+export class HomeComponent implements OnInit {
+ title = 'Energy Price Dashboard';
+ priceData: EnergyPrice[] = [];
+ loading = true;
+ error = '';
+
+ regions = [
+ { value: 'SE1', label: 'Luleå / Norra Sverige' },
+ { value: 'SE2', label: 'Sundsvall / Norra Mellansverige' },
+ { value: 'SE3', label: 'Stockholm / Södra Mellansverige' },
+ { value: 'SE4', label: 'Malmö / Södra Sverige' }
+ ];
+
+ // Default values
+ selectedDate = new Date();
+ // Default will be overridden by localStorage if available
+ selectedRegion = this.regions[Math.floor(Math.random() * this.regions.length)].value;
+
+ private energyPriceService = inject(EnergyPriceService);
+ private datePipe = inject(DatePipe);
+
+ ngOnInit() {
+ // Load saved region from localStorage if available
+ const savedRegion = localStorage.getItem('selectedRegion');
+ if (savedRegion) {
+ this.selectedRegion = savedRegion;
+ }
+
+ this.loadPriceData();
+ }
+
+ loadPriceData() {
+ this.loading = true;
+ this.error = '';
+
+ const { year, month, day } = this.energyPriceService.formatDate(this.selectedDate);
+
+ this.energyPriceService.getPrices(year, month, day, this.selectedRegion)
+ .subscribe({
+ next: (data) => {
+ this.priceData = data;
+ this.loading = false;
+ },
+ error: (err) => {
+ this.error = 'Failed to load energy price data. Please try again later.';
+ this.loading = false;
+ console.error('Error fetching price data:', err);
+ }
+ });
+ }
+
+ onRegionChange() {
+ // Save selected region to localStorage
+ localStorage.setItem('selectedRegion', this.selectedRegion);
+ this.loadPriceData();
+ }
+
+ onDateChange(event: Event) {
+ // Fix: properly handle date input event
+ const inputElement = event.target as HTMLInputElement;
+ if (inputElement.value) {
+ this.selectedDate = new Date(inputElement.value);
+ this.loadPriceData();
+ }
+ }
+
+ get maxDate(): string {
+ const today = new Date();
+ return today.toISOString().split('T')[0];
+ }
+
+ get formattedDate(): string {
+ 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;
+ }
+}
diff --git a/src/app/energy-price.service.ts b/src/app/services/energy-price.service.ts
similarity index 100%
rename from src/app/energy-price.service.ts
rename to src/app/services/energy-price.service.ts
diff --git a/src/main.ts b/src/main.ts
index 4e6be2b..83b8548 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -1,11 +1,6 @@
import { bootstrapApplication } from '@angular/platform-browser';
-import { provideHttpClient } from '@angular/common/http';
-import { provideCharts, withDefaultRegisterables } from 'ng2-charts';
+import { appConfig } from './app/app.config';
import { AppComponent } from './app/app.component';
-bootstrapApplication(AppComponent, {
- providers: [
- provideHttpClient(),
- provideCharts(withDefaultRegisterables())
- ]
-}).catch(err => console.error(err));
+bootstrapApplication(AppComponent, appConfig)
+ .catch(err => console.error(err));