diff --git a/amp-client/src/Pages/ClientPages/ClientDashboard/ClientDashboard.jsx b/amp-client/src/Pages/ClientPages/ClientDashboard/ClientDashboard.jsx index 41207aba..d7b37ff1 100644 --- a/amp-client/src/Pages/ClientPages/ClientDashboard/ClientDashboard.jsx +++ b/amp-client/src/Pages/ClientPages/ClientDashboard/ClientDashboard.jsx @@ -1,5 +1,5 @@ import "./styles.css"; -import { Line } from "react-chartjs-2"; +import { Line, Bar } from "react-chartjs-2"; import { useState, useEffect } from "react"; import axiosBaseUrl from "../../../Axios/axios"; import { useDispatch, useSelector } from "react-redux"; @@ -10,6 +10,7 @@ import { LinearScale, PointElement, LineElement, + BarElement, Title, Tooltip, Legend, @@ -20,10 +21,11 @@ ChartJS.register( LinearScale, PointElement, LineElement, + BarElement, Title, Tooltip, Legend, - Filler, + Filler ); const ClientDashboard = () => { @@ -67,7 +69,12 @@ const ClientDashboard = () => { } if (!dashboardData) { - return
No dashboard data available.
; + return ( +
+
+

Loading dashboard data...

+
+ ); } const powerUsageData = { @@ -78,7 +85,7 @@ const ClientDashboard = () => { data: Object.values(dashboardData.powerUsagePerDay), fill: true, backgroundColor: "rgba(75, 192, 192, 0.6)", - borderColor: "#28a745", // Bootstrap success color + borderColor: "#28a745", pointBackgroundColor: "#28a745", pointBorderColor: "#fff", tension: 0.3, @@ -91,22 +98,28 @@ const ClientDashboard = () => { datasets: [ { label: "Cumulative Power Usage (in Kilowatts)", - data: Object.values(dashboardData.cumulativePowerUsage), - fill: true, - backgroundColor: "rgba(255, 193, 7, 0.6)", // Bootstrap warning color + data: Object.values(dashboardData.cumulativePowerUsage).map( + (arr) => Math.max(...arr) + ), + backgroundColor: "rgba(255, 193, 7, 0.6)", borderColor: "#ffc107", - pointBackgroundColor: "#ffc107", - pointBorderColor: "#fff", - tension: 0.3, + borderWidth: 1, }, ], }; const chartOptions = { responsive: true, + maintainAspectRatio: false, + layout: { + padding: { + top: 0, + bottom: 0, + }, + }, plugins: { legend: { - position: "top", + position: "bottom", }, title: { display: true, @@ -127,6 +140,8 @@ const ClientDashboard = () => { }, }, y: { + beginAtZero: true, + min: 0, title: { display: true, text: "Kilowatts", @@ -135,7 +150,6 @@ const ClientDashboard = () => { grid: { borderColor: "#eee", }, - beginAtZero: true, }, }, }; @@ -154,10 +168,6 @@ const ClientDashboard = () => { ...chartOptions, plugins: { ...chartOptions.plugins, - title: { - ...chartOptions.plugins.title, - text: "Power Usage per Day", - }, }, }} /> @@ -169,16 +179,12 @@ const ClientDashboard = () => {

Cumulative Power Usage Per Day

{Object.keys(cumulativePowerUsageData.labels).length > 0 ? ( - diff --git a/amp-client/src/Pages/ClientPages/ClientDashboard/styles.css b/amp-client/src/Pages/ClientPages/ClientDashboard/styles.css index 9caab74f..7860886b 100644 --- a/amp-client/src/Pages/ClientPages/ClientDashboard/styles.css +++ b/amp-client/src/Pages/ClientPages/ClientDashboard/styles.css @@ -43,9 +43,14 @@ } .chart-widget { - flex: 1; + flex: 1; + height: 350px; + display: flex; + flex-direction: column; + justify-content: flex-end; background-color: #fff; padding: 15px; + margin-top: 10px; border-radius: 8px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.05); border: 1px solid #eee; @@ -78,3 +83,29 @@ font-weight: bold; color: #198754; } + +.spinner-container { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: 150px; + color: #555; + width: 100%; +} + +.spinner { + width: 40px; + height: 40px; + border: 4px solid rgba(0, 0, 0, 0.1); + border-left-color: #f9a43a; + border-radius: 50%; + animation: spin 1s linear infinite; + margin-bottom: 10px; +} + +@keyframes spin { + to { + transform: rotate(360deg); + } +} diff --git a/amp-client/src/Pages/ProviderPages/ProviderDashboard/ProviderDashboard.jsx b/amp-client/src/Pages/ProviderPages/ProviderDashboard/ProviderDashboard.jsx index 28ca7daa..2d539fd8 100644 --- a/amp-client/src/Pages/ProviderPages/ProviderDashboard/ProviderDashboard.jsx +++ b/amp-client/src/Pages/ProviderPages/ProviderDashboard/ProviderDashboard.jsx @@ -102,20 +102,24 @@ const ProviderDashboard = () => { const totalPowerUsageResponse = await axiosBaseUrl.get( `/providers/totalPowerUsage/${userId}` ); - setTotalPowerUsage( - Array.isArray(totalPowerUsageResponse?.data?.data) - ? totalPowerUsageResponse.data.data - : [] - ); + const totalPowerUsageArray = Object.entries( + totalPowerUsageResponse.data.data + ).map(([date, power]) => ({ + timestamp: new Date(date).toISOString(), + total_power: power, + })); + setTotalPowerUsage(totalPowerUsageArray); const averageVoltageResponse = await axiosBaseUrl.get( `/providers/averageVoltage/${userId}` ); - setAverageVoltage( - Array.isArray(averageVoltageResponse?.data?.data) - ? averageVoltageResponse.data.data - : [] - ); + const averageVoltageArray = Object.entries( + averageVoltageResponse.data.data + ).map(([date, voltage]) => ({ + timestamp: new Date(date).toISOString(), + average_voltage: voltage, + })); + setAverageVoltage(averageVoltageArray); const usersResponse = await axiosBaseUrl.get( `/providers/getAllUsers/${userId}` @@ -134,9 +138,14 @@ const ProviderDashboard = () => { const linesResponse = await axiosBaseUrl.get( `/providers/getAllLines/${userId}` ); - setTotalLines(usersResponse?.data?.data?.length); + setTotalLines(linesResponse?.data?.data?.length); } catch (err) { - setError(err.message || "Failed to fetch dashboard data for charts"); + if (err.code === "ECONNABORTED") { + setError("Request timed out. Please try again."); + } else { + setError(err.message || "Failed to fetch dashboard data for charts"); + } + // setError(err.message || "Failed to fetch dashboard data for charts"); console.error("Error fetching dashboard data for charts:", err); } finally { setLoading(false); @@ -171,6 +180,28 @@ const ProviderDashboard = () => { const chartOptions = { responsive: true, maintainAspectRatio: true, + plugins: { + legend: { + position: "bottom", + }, + title: { + display: true, + text: "Chart", + font: { + size: 14, + }, + }, + }, + scales: { + y: { + beginAtZero: true, + }, + }, + }; + + const voltageLineChartOptions = { + responsive: true, + maintainAspectRatio: false, plugins: { legend: { position: "bottom", @@ -185,6 +216,8 @@ const ProviderDashboard = () => { scales: { y: { beginAtZero: true, + min: 200, + max: 250, }, }, }; @@ -206,6 +239,7 @@ const ProviderDashboard = () => { scales: { y: { beginAtZero: true, + // min: 100, }, }, }; @@ -243,7 +277,7 @@ const ProviderDashboard = () => { { label: "Frequency", data: voltageDistribution.map((v) => v[1]), - backgroundColor: "rgba(201, 203, 207, 0.8)", + backgroundColor: "rgba(3, 60, 173, 0.8)", borderColor: "rgb(201, 203, 207)", borderWidth: 1, }, @@ -307,7 +341,9 @@ const ProviderDashboard = () => { const totalPowerUsageData = { labels: Array.isArray(totalPowerUsage) ? totalPowerUsage.map((item) => - new Date(item.timestamp).toLocaleDateString() + item.timestamp + ? new Date(item.timestamp).toLocaleDateString() + : "Invalid" ) : [], datasets: [ @@ -367,7 +403,7 @@ const ProviderDashboard = () => { ) : ( @@ -382,6 +418,7 @@ const ProviderDashboard = () => { key="voltageDistributionChart" data={voltageDistributionData} options={lineChartOptions} + // options={chartOptions} ref={voltageDistributionChartRef} /> ) : ( @@ -419,11 +456,11 @@ const ProviderDashboard = () => {

Total Power Usage Over Time

- {totalPowerUsage.length > 0 ? ( + {totalPowerUsage !== null && totalPowerUsage !== undefined ? ( ) : ( @@ -433,11 +470,12 @@ const ProviderDashboard = () => {

Average Voltage Over Time

- {averageVoltage.length > 0 ? ( + {averageVoltage !== null && averageVoltage !== undefined ? ( ) : ( @@ -461,21 +499,27 @@ const ProviderDashboard = () => {

All Metrics

- {allMetrics.length > 0 ? ( + {allMetrics && Object.keys(allMetrics).length > 0 ? ( - - + + + + + {allMetrics.map((metric, index) => ( - - - - + + + + + + + ))} diff --git a/amp-client/src/Pages/ProviderPages/ProviderDashboard/styles.css b/amp-client/src/Pages/ProviderPages/ProviderDashboard/styles.css index e2e8c7c3..0b5d6168 100644 --- a/amp-client/src/Pages/ProviderPages/ProviderDashboard/styles.css +++ b/amp-client/src/Pages/ProviderPages/ProviderDashboard/styles.css @@ -52,11 +52,12 @@ .chart-widget { flex: 1; - min-width: 250px; + min-width: 300px; max-width: 500px; max-height: 450px; + height: 350px; background-color: #fff; - padding: 15px; + padding: 30px; border-radius: 8px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.05); border: 1px solid #eee; @@ -75,7 +76,7 @@ .voltage-distribution-widget { height: 350px; - max-height: 400px; + max-height: 450px; } .metric-card { diff --git a/amp-laravel/app/Services/Provider/GetAverageVoltageService.php b/amp-laravel/app/Services/Provider/GetAverageVoltageService.php index 65d1018c..a90cae97 100644 --- a/amp-laravel/app/Services/Provider/GetAverageVoltageService.php +++ b/amp-laravel/app/Services/Provider/GetAverageVoltageService.php @@ -2,15 +2,35 @@ namespace App\Services\Provider; +use DateTime; use App\Models\Master; use App\Models\Metric; -use App\Models\User; class GetAverageVoltageService { - public static function getAverageVoltage(int $providerId): float + public static function getAverageVoltage(int $providerId): array { $masterIds = Master::where('user_id', $providerId)->pluck('id'); - return round(Metric::whereIn('master_id', $masterIds)->avg('voltage'), 2); + + $averageVoltageByDay = Metric::whereIn('master_id', $masterIds) + ->selectRaw('SUBSTRING(date_month, 1, 5) as day_month, AVG(voltage) as average_voltage') + ->groupBy('day_month') + ->orderBy('day_month') + ->get() + ->mapWithKeys(function ($item) { + try { + $date = DateTime::createFromFormat('m-d', $item->day_month); + if ($date) { + return [$date->format('Y-m-d') => round($item->average_voltage, 2)]; + } + } catch (\Exception $e) { + return []; + } + return []; + }) + ->filter() + ->toArray(); + + return $averageVoltageByDay; } } diff --git a/amp-laravel/app/Services/Provider/GetTotalPowerUsageService.php b/amp-laravel/app/Services/Provider/GetTotalPowerUsageService.php index 1f9f03da..33c32033 100644 --- a/amp-laravel/app/Services/Provider/GetTotalPowerUsageService.php +++ b/amp-laravel/app/Services/Provider/GetTotalPowerUsageService.php @@ -2,17 +2,37 @@ namespace App\Services\Provider; +use DateTime; use App\Models\Master; use App\Models\Metric; +use Illuminate\Support\Collection; class GetTotalPowerUsageService { - public static function getTotalPowerUsage(int $providerId): float + public static function getTotalPowerUsage(int $providerId): array { $masterIds = Master::where('user_id', $providerId)->pluck('id'); - return round(Metric::whereIn('master_id', $masterIds) - ->whereRaw('SUBSTRING(date_month, 1, 2) = ?', [now()->format('m')]) - ->sum('power'), 2); + $totalPowerUsageByDay = Metric::whereIn('master_id', $masterIds) + ->selectRaw('SUBSTRING(date_month, 1, 5) as day_month, SUM(power) as total_power') + ->groupBy('day_month') + ->orderBy('day_month') + ->get() + ->mapWithKeys(function ($item) { + try { + $date = DateTime::createFromFormat('m-d', $item->day_month); + if ($date) { + return [$date->format('Y-m-d') => round($item->total_power, 2)]; + } + } catch (\Exception $e) { + // Log or handle parsing errors as needed + return []; + } + return []; + }) + ->filter() + ->toArray(); + + return $totalPowerUsageByDay; } }
MetricValueIDVoltageCurrentPowerEnergy Timestamp
{metric.metric_name}{metric.metric_value}{new Date(metric.timestamp).toLocaleString()}
{metric.id}{metric.voltage}{metric.current}{metric.power}{metric.energy}{new Date(metric.created_at).toLocaleString()}