diff --git a/package-lock.json b/package-lock.json
index 17c2478..2d50301 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -17,6 +17,7 @@
"@angular/platform-browser-dynamic": "^17.3.0",
"@angular/router": "^17.3.0",
"@coreui/coreui": "^5.1.2",
+ "apexcharts": "^3.53.0",
"bootstrap": "^5.3.3",
"ngx-toastr": "^19.0.0",
"rxjs": "~7.8.0",
@@ -4261,6 +4262,11 @@
"dev": true,
"license": "BSD-2-Clause"
},
+ "node_modules/@yr/monotone-cubic-spline": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@yr/monotone-cubic-spline/-/monotone-cubic-spline-1.0.3.tgz",
+ "integrity": "sha512-FQXkOta0XBSUPHndIKON2Y9JeQz5ZeMqLYZVVK93FliNBFm7LNMIZmY6FrMEB9XPcDbE2bekMbZD6kzDkxwYjA=="
+ },
"node_modules/abbrev": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz",
@@ -4501,6 +4507,20 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
+ "node_modules/apexcharts": {
+ "version": "3.53.0",
+ "resolved": "https://registry.npmjs.org/apexcharts/-/apexcharts-3.53.0.tgz",
+ "integrity": "sha512-QESZHZY3w9LPQ64PGh1gEdfjYjJ5Jp+Dfy0D/CLjsLOPTpXzdxwlNMqRj+vPbTcP0nAHgjWv1maDqcEq6u5olw==",
+ "dependencies": {
+ "@yr/monotone-cubic-spline": "^1.0.3",
+ "svg.draggable.js": "^2.2.2",
+ "svg.easing.js": "^2.0.0",
+ "svg.filter.js": "^2.0.2",
+ "svg.pathmorphing.js": "^0.1.3",
+ "svg.resize.js": "^1.4.3",
+ "svg.select.js": "^3.0.1"
+ }
+ },
"node_modules/argparse": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
@@ -11985,6 +12005,89 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/svg.draggable.js": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/svg.draggable.js/-/svg.draggable.js-2.2.2.tgz",
+ "integrity": "sha512-JzNHBc2fLQMzYCZ90KZHN2ohXL0BQJGQimK1kGk6AvSeibuKcIdDX9Kr0dT9+UJ5O8nYA0RB839Lhvk4CY4MZw==",
+ "dependencies": {
+ "svg.js": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/svg.easing.js": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/svg.easing.js/-/svg.easing.js-2.0.0.tgz",
+ "integrity": "sha512-//ctPdJMGy22YoYGV+3HEfHbm6/69LJUTAqI2/5qBvaNHZ9uUFVC82B0Pl299HzgH13rKrBgi4+XyXXyVWWthA==",
+ "dependencies": {
+ "svg.js": ">=2.3.x"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/svg.filter.js": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/svg.filter.js/-/svg.filter.js-2.0.2.tgz",
+ "integrity": "sha512-xkGBwU+dKBzqg5PtilaTb0EYPqPfJ9Q6saVldX+5vCRy31P6TlRCP3U9NxH3HEufkKkpNgdTLBJnmhDHeTqAkw==",
+ "dependencies": {
+ "svg.js": "^2.2.5"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/svg.js": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/svg.js/-/svg.js-2.7.1.tgz",
+ "integrity": "sha512-ycbxpizEQktk3FYvn/8BH+6/EuWXg7ZpQREJvgacqn46gIddG24tNNe4Son6omdXCnSOaApnpZw6MPCBA1dODA=="
+ },
+ "node_modules/svg.pathmorphing.js": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/svg.pathmorphing.js/-/svg.pathmorphing.js-0.1.3.tgz",
+ "integrity": "sha512-49HWI9X4XQR/JG1qXkSDV8xViuTLIWm/B/7YuQELV5KMOPtXjiwH4XPJvr/ghEDibmLQ9Oc22dpWpG0vUDDNww==",
+ "dependencies": {
+ "svg.js": "^2.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/svg.resize.js": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/svg.resize.js/-/svg.resize.js-1.4.3.tgz",
+ "integrity": "sha512-9k5sXJuPKp+mVzXNvxz7U0uC9oVMQrrf7cFsETznzUDDm0x8+77dtZkWdMfRlmbkEEYvUn9btKuZ3n41oNA+uw==",
+ "dependencies": {
+ "svg.js": "^2.6.5",
+ "svg.select.js": "^2.1.2"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/svg.resize.js/node_modules/svg.select.js": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/svg.select.js/-/svg.select.js-2.1.2.tgz",
+ "integrity": "sha512-tH6ABEyJsAOVAhwcCjF8mw4crjXSI1aa7j2VQR8ZuJ37H2MBUbyeqYr5nEO7sSN3cy9AR9DUwNg0t/962HlDbQ==",
+ "dependencies": {
+ "svg.js": "^2.2.5"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/svg.select.js": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/svg.select.js/-/svg.select.js-3.0.1.tgz",
+ "integrity": "sha512-h5IS/hKkuVCbKSieR9uQCj9w+zLHoPh+ce19bBYyqF53g6mnPB8sAtIbe1s9dh2S2fCmYX2xel1Ln3PJBbK4kw==",
+ "dependencies": {
+ "svg.js": "^2.6.5"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
"node_modules/symbol-observable": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz",
diff --git a/package.json b/package.json
index 4e52b19..033e413 100644
--- a/package.json
+++ b/package.json
@@ -19,6 +19,7 @@
"@angular/platform-browser-dynamic": "^17.3.0",
"@angular/router": "^17.3.0",
"@coreui/coreui": "^5.1.2",
+ "apexcharts": "^3.53.0",
"bootstrap": "^5.3.3",
"ngx-toastr": "^19.0.0",
"rxjs": "~7.8.0",
diff --git a/src/app/views/energy-overview/energy-overview.component.html b/src/app/views/energy-overview/energy-overview.component.html
index 9535755..843d174 100644
--- a/src/app/views/energy-overview/energy-overview.component.html
+++ b/src/app/views/energy-overview/energy-overview.component.html
@@ -1,26 +1,34 @@
-
+
Welcome to the Energy Data Component!
This is a simple Angular component.
-
-
-
-
- Batterielevel |
- Batterie Prozent |
- Batterie Spannung |
- Batterie Status |
- Zeitpunkt |
-
-
- {{ data.batteryLevel }} |
- {{ data.batteryPercent }} |
- {{ data.batteryVoltage }} |
- {{ data.batteryStatus }} |
- {{ data.occuredAt | date }} |
-
-
+
+
+
+
+
+ {{ data.batteryLevel }} |
+ {{ data.batteryPercent }} |
+ {{ data.batteryVoltage }} |
+ {{ data.batteryStatus }} |
+ {{ data.occuredAt | date }} |
+
+
+
diff --git a/src/app/views/energy-overview/energy-overview.component.ts b/src/app/views/energy-overview/energy-overview.component.ts
index 7c747f9..3848f9c 100644
--- a/src/app/views/energy-overview/energy-overview.component.ts
+++ b/src/app/views/energy-overview/energy-overview.component.ts
@@ -1,23 +1,105 @@
-import { Component, Inject, OnInit } from '@angular/core';
+import {
+ AfterViewInit,
+ Component,
+ ElementRef,
+ Inject,
+ OnInit,
+ ViewChild,
+} from '@angular/core';
import { EnergyDataService } from '../../services/energy-data.service';
+import ApexCharts, { ApexOptions } from 'apexcharts';
@Component({
selector: 'app-energy-overview',
templateUrl: './energy-overview.component.html',
styleUrls: ['./energy-overview.component.scss'],
})
-export class EnergyOverviewComponent implements OnInit {
+export class EnergyOverviewComponent implements OnInit, AfterViewInit {
constructor(
@Inject(EnergyDataService) private readonly energyService: EnergyDataService
) {}
+ @ViewChild('batteryChart') chart?: ElementRef
;
energyData: any;
+ mockDate = new Date();
mockData = [
+ // {
+ // batteryLevel: 40,
+ // batteryPercent: '50%',
+ // batteryStatus: 'Charging',
+ // batteryVoltage: '12.5',
+ // occuredAt: this.mockDate,
+ // },
+ {
+ batteryLevel: 10,
+ batteryPercent: '50%',
+ batteryStatus: 'Charging',
+ batteryVoltage: '12.5',
+ occuredAt: new Date(
+ this.mockDate.setHours(this.mockDate.getHours() - 10)
+ ),
+ },
+ {
+ batteryLevel: 15,
+ batteryPercent: '50%',
+ batteryStatus: 'Charging',
+ batteryVoltage: '12.5',
+ occuredAt: new Date(this.mockDate.setHours(this.mockDate.getHours() - 9)),
+ },
+ {
+ batteryLevel: 33,
+ batteryPercent: '50%',
+ batteryStatus: 'Charging',
+ batteryVoltage: '12.5',
+ occuredAt: new Date(this.mockDate.setHours(this.mockDate.getHours() - 8)),
+ },
+ {
+ batteryLevel: 25,
+ batteryPercent: '50%',
+ batteryStatus: 'Charging',
+ batteryVoltage: '12.5',
+ occuredAt: new Date(this.mockDate.setHours(this.mockDate.getHours() - 7)),
+ },
{
batteryLevel: 50,
batteryPercent: '50%',
batteryStatus: 'Charging',
batteryVoltage: '12.5',
- occuredAt: new Date(),
+ occuredAt: new Date(this.mockDate.setHours(this.mockDate.getHours() - 6)),
+ },
+ {
+ batteryLevel: 64,
+ batteryPercent: '50%',
+ batteryStatus: 'Charging',
+ batteryVoltage: '12.5',
+ occuredAt: new Date(this.mockDate.setHours(this.mockDate.getHours() - 5)),
+ },
+ {
+ batteryLevel: 80,
+ batteryPercent: '50%',
+ batteryStatus: 'Charging',
+ batteryVoltage: '12.5',
+ occuredAt: new Date(this.mockDate.setHours(this.mockDate.getHours() - 4)),
+ },
+ {
+ batteryLevel: 100,
+ batteryPercent: '50%',
+ batteryStatus: 'Charging',
+ batteryVoltage: '12.5',
+ occuredAt: new Date(this.mockDate.setHours(this.mockDate.getHours() - 3)),
+ },
+ {
+ batteryLevel: 78,
+ batteryPercent: '50%',
+ batteryStatus: 'Charging',
+ batteryVoltage: '12.5',
+ occuredAt: new Date(this.mockDate.setHours(this.mockDate.getHours() - 2)),
+ },
+ {
+ batteryLevel: 54,
+ batteryPercent: '50%',
+ batteryStatus: 'Charging',
+ batteryVoltage: '12.5',
+ occuredAt: new Date(this.mockDate.setHours(this.mockDate.getHours() - 1)),
},
];
ngOnInit(): void {
@@ -25,4 +107,74 @@ export class EnergyOverviewComponent implements OnInit {
this.energyData = data;
});
}
+
+ ngAfterViewInit() {
+ this.drawChart();
+ }
+
+ drawChart(force = false) {
+ // if (!this.mockData) return;
+ // if (this.chart?.nativeElement.hasChildNodes()) {
+ // if (force) this.chart.nativeElement.innerHTML = '';
+ // else return;
+ // }
+ const values: { x: number; y: number }[] = [];
+ if (this.mockData)
+ this.mockData.forEach((h: any) => {
+ const value = h.batteryLevel;
+ const timestamp = new Date(h.occuredAt).getTime();
+ values.unshift({ x: timestamp, y: value });
+ });
+ const options: ApexOptions = {
+ series: [
+ {
+ name: 'Ladestatus in %',
+ data: values,
+ },
+ ],
+ chart: {
+ id: 'area-datetime',
+ type: 'area',
+ height: 400,
+ zoom: {
+ enabled: true,
+ },
+ animations: {
+ enabled: false,
+ },
+ },
+ stroke: {
+ curve: 'smooth',
+ },
+ dataLabels: {
+ enabled: false,
+ },
+ xaxis: {
+ type: 'datetime',
+ labels: {
+ datetimeUTC: false,
+ },
+ },
+ yaxis: {
+ min: 0,
+ max: 100,
+ },
+ tooltip: {
+ x: {
+ format: 'dd MMM yyyy, HH mm',
+ },
+ },
+ fill: {
+ type: 'gradient',
+ gradient: {
+ shadeIntensity: 1,
+ opacityFrom: 0.7,
+ opacityTo: 0.9,
+ stops: [0, 100],
+ },
+ },
+ colors: ['#4DBD74'],
+ };
+ new ApexCharts(this.chart?.nativeElement, options).render();
+ }
}