dev smartfarming #1

Merged
agrilink merged 53 commits from development into main 2024-12-30 05:53:19 +00:00
3 changed files with 119 additions and 74 deletions
Showing only changes of commit c405a9d815 - Show all commits

View File

@ -12,38 +12,9 @@
<div class="title-graph" *ngIf="selectedButton === 'npk1'">Actual Graph Sensor NPK 1</div> <div class="title-graph" *ngIf="selectedButton === 'npk1'">Actual Graph Sensor NPK 1</div>
<div class="title-graph" *ngIf="selectedButton === 'npk2'">Actual Graph Sensor NPK 2</div> <div class="title-graph" *ngIf="selectedButton === 'npk2'">Actual Graph Sensor NPK 2</div>
<div class="graph-content"> <div class="graph-content">
<table class="table parameter" *ngIf="!isLoading && !isNoData" style="padding-top: 0px;"> <canvas #barChart></canvas>
<thead> <!-- <i *ngIf="isLoading" class="fa fa-spinner fa-spin spinner"></i>
<tr> <p *ngIf="isNoData" class="no-data">No available data</p> -->
<th scope="col">#</th>
<th scope="col">Parameter</th>
<th scope="col">Actual Data</th>
<th scope="col">Standard Data</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">1</th>
<td>Nitrogen</td>
<td>{{ actualDataValues.nitrogen }} mg/L</td>
<td>100-200 mg/L</td>
</tr>
<tr>
<th scope="row">2</th>
<td>Phosphorus</td>
<td>{{ actualDataValues.phosphorus }} mg/L</td>
<td>90-125 mg/L</td>
</tr>
<tr>
<th scope="row">3</th>
<td>Kalium</td>
<td>{{ actualDataValues.kalium }} mg/L</td>
<td>220-240 mg/L</td>
</tr>
</tbody>
</table>
<i *ngIf="isLoading" class="fa fa-spinner fa-spin spinner"></i>
<p *ngIf="isNoData" class="no-data">No available data</p>
</div> </div>
</div> </div>
</div> </div>

View File

@ -14,22 +14,27 @@
margin: 10px 0px 15px 0px; margin: 10px 0px 15px 0px;
} }
.graph {
width: 100%;
height: 400px;
position: relative;
max-width: 100%;
border-radius: 10px;
border: 1px solid #E5E5E5;
padding: 20px 20px 0px 20px;
.graph {
position: relative;
width: 100%;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: flex-start;
align-items: center; align-items: center;
text-align: center; margin-bottom: 35px;
border: 1px solid #E5E5E5;
padding: 0px 20px 0px 20px;
background-color: white;
border-radius: 10px;
margin-top: 20px; margin-top: 20px;
overflow-x: auto;
canvas {
position: relative;
width: 100%;
height: auto;
aspect-ratio: 2 / 1;
max-height: 300px;
}
} }
.table th, .table th,
@ -51,7 +56,7 @@
align-items: center; align-items: center;
width: 100%; width: 100%;
height: 100%; height: 100%;
padding-top: 30px; padding-top: 20px;
color: #49473C; color: #49473C;
} }
@ -64,16 +69,20 @@
@media (max-width: 768px) { @media (max-width: 768px) {
.graph { .graph {
height: 300px; height: 300px;
padding: 10px;
} }
.title-graph { .title-graph {
margin: auto;
font-size: 15px; font-size: 15px;
} }
.table{ .table {
font-size: 10px; font-size: 10px;
} }
canvas {
max-width: 300px;
}
} }
@media (max-width: 344px) { @media (max-width: 344px) {
@ -85,12 +94,15 @@
.title-graph { .title-graph {
font-size: 15px; font-size: 15px;
margin: auto;
} }
.table{ .table {
font-size: 10px; font-size: 10px;
} }
canvas {
max-width: 250px;
}
} }
button { button {

View File

@ -1,10 +1,9 @@
import { Component, OnInit, ViewChild, ElementRef, ChangeDetectorRef } from '@angular/core'; import { Component, OnInit, ViewChild, ElementRef, ChangeDetectorRef } from '@angular/core';
import { Chart, registerables } from 'chart.js';
import { SensorService } from '../../../../cores/services/sensor.service'; import { SensorService } from '../../../../cores/services/sensor.service';
import { ApiResponse, ParameterSensor } from '../../../../cores/interface/sensor-data'; import { ApiResponse, ParameterSensor } from '../../../../cores/interface/sensor-data';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { Chart } from 'chart.js';
Chart.register(...registerables); import { max } from 'date-fns';
@Component({ @Component({
selector: 'app-actualgraph', selector: 'app-actualgraph',
@ -14,17 +13,16 @@ Chart.register(...registerables);
styleUrls: ['./actualgraph.component.scss'] styleUrls: ['./actualgraph.component.scss']
}) })
export class ActualgraphComponent implements OnInit { export class ActualgraphComponent implements OnInit {
@ViewChild('chartCanvas', { static: false }) chartCanvas?: ElementRef<HTMLCanvasElement>; @ViewChild('barChart') barChart!: ElementRef;
private chart: Chart | undefined;
selectedButton: string = 'npk1'; selectedButton: string = 'npk1';
isLoading: boolean = true;
isNoData: boolean = false;
greeting = ''; greeting = '';
actualDataValues = { chart: any;
nitrogen: 0, actualDataValues = { nitrogen: 0, phosphorus: 0, kalium: 0 };
phosphorus: 0, standardDataValues = {
kalium: 0 nitrogen: { min: 100, max: 200 },
phosphorus: { min: 90, max: 125 },
kalium: { min: 220, max: 240 }
}; };
constructor( constructor(
@ -37,10 +35,71 @@ export class ActualgraphComponent implements OnInit {
this.loadData('npk1'); this.loadData('npk1');
} }
ngAfterViewInit(): void {
this.initChart();
}
initChart(): void {
const minStandard = [
this.standardDataValues.nitrogen.min,
this.standardDataValues.phosphorus.min,
this.standardDataValues.kalium.min
];
const maxStandard = [
this.standardDataValues.nitrogen.max,
this.standardDataValues.phosphorus.max,
this.standardDataValues.kalium.max
];
this.chart = new Chart(this.barChart.nativeElement, {
type: 'bar',
data: {
labels: ['Nitrogen', 'Phosphorus', 'Kalium'],
datasets: [
{
label: 'Min Standard',
backgroundColor: 'rgba(0, 0, 0, 0)',
data: minStandard,
borderWidth: 0
},
{
label: 'Max Standard',
backgroundColor: 'rgba(212, 231, 197)',
data: maxStandard,
borderWidth: 1
},
{
label: 'Actual Data',
type: 'scatter',
backgroundColor: 'rgba(18, 55, 42)',
borderColor: 'rgba(18, 55, 10)',
pointRadius: 5,
pointHoverRadius: 7,
data: [
{ x: 'Nitrogen', y: this.actualDataValues.nitrogen },
{ x: 'Phosphorus', y: this.actualDataValues.phosphorus },
{ x: 'Kalium', y: this.actualDataValues.kalium }
],
}
]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
x: { stacked: true },
y: {
stacked: true,
beginAtZero: false,
}
}
}
});
}
loadData(sensorType: string): void { loadData(sensorType: string): void {
this.selectedButton = sensorType; this.selectedButton = sensorType;
this.isLoading = true;
this.isNoData = false;
this.sensorService.getLatestData().subscribe( this.sensorService.getLatestData().subscribe(
(response: ApiResponse) => { (response: ApiResponse) => {
@ -55,28 +114,31 @@ export class ActualgraphComponent implements OnInit {
phosphorus: npkData.soilphosphorus ?? 0, phosphorus: npkData.soilphosphorus ?? 0,
kalium: npkData.soilpotassium ?? 0 kalium: npkData.soilpotassium ?? 0
}; };
this.updateChart();
this.isLoading = false;
this.cdr.detectChanges();
} else { } else {
this.isNoData = true;
this.isLoading = false;
this.cdr.detectChanges();
} }
} else { } else {
console.error('Error loading data: ', response.message); console.error('Error loading data: ', response.message);
this.isLoading = false;
this.cdr.detectChanges();
} }
}, },
(error) => { (error) => {
console.error('Error loading data:', error); console.error('Error loading data:', error);
this.isLoading = false;
this.cdr.detectChanges(); this.cdr.detectChanges();
} }
); );
} }
updateChart(): void {
if (this.chart) {
this.chart.data.datasets[2].data = [
{ x: 'Nitrogen', y: this.actualDataValues.nitrogen },
{ x: 'Phosphorus', y: this.actualDataValues.phosphorus },
{ x: 'Kalium', y: this.actualDataValues.kalium }
];
this.chart.update();
}
}
updateGreeting(): void { updateGreeting(): void {
const hour = new Date().getHours(); const hour = new Date().getHours();
this.greeting = hour < 12 ? 'Good Morning' : hour < 18 ? 'Good Afternoon' : 'Good Evening'; this.greeting = hour < 12 ? 'Good Morning' : hour < 18 ? 'Good Afternoon' : 'Good Evening';