Add EnergyConsumptionPerDevice functionality and update related components

This commit is contained in:
Faris Armoush
2025-05-05 10:29:44 +03:00
parent 696978a78d
commit 06637a16bb
5 changed files with 135 additions and 79 deletions

View File

@ -1,11 +1,13 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/analytics/modules/energy_management/blocs/energy_consumption_by_phases/energy_consumption_by_phases_bloc.dart'; import 'package:syncrow_web/pages/analytics/modules/energy_management/blocs/energy_consumption_by_phases/energy_consumption_by_phases_bloc.dart';
import 'package:syncrow_web/pages/analytics/modules/energy_management/blocs/energy_consumption_per_device/energy_consumption_per_device_bloc.dart';
import 'package:syncrow_web/pages/analytics/modules/energy_management/blocs/total_energy_consumption/total_energy_consumption_bloc.dart'; import 'package:syncrow_web/pages/analytics/modules/energy_management/blocs/total_energy_consumption/total_energy_consumption_bloc.dart';
import 'package:syncrow_web/pages/analytics/modules/energy_management/widgets/energy_consumption_per_device_chart_box.dart'; import 'package:syncrow_web/pages/analytics/modules/energy_management/widgets/energy_consumption_per_device_chart_box.dart';
import 'package:syncrow_web/pages/analytics/modules/energy_management/widgets/power_clamp_energy_data_widget.dart'; import 'package:syncrow_web/pages/analytics/modules/energy_management/widgets/power_clamp_energy_data_widget.dart';
import 'package:syncrow_web/pages/analytics/modules/energy_management/widgets/total_energy_consumption_chart_box.dart'; import 'package:syncrow_web/pages/analytics/modules/energy_management/widgets/total_energy_consumption_chart_box.dart';
import 'package:syncrow_web/pages/analytics/params/get_energy_consumption_by_phases_param.dart'; import 'package:syncrow_web/pages/analytics/params/get_energy_consumption_by_phases_param.dart';
import 'package:syncrow_web/pages/analytics/params/get_energy_consumption_per_device_param.dart';
import 'package:syncrow_web/pages/analytics/params/get_total_energy_consumption_param.dart'; import 'package:syncrow_web/pages/analytics/params/get_total_energy_consumption_param.dart';
import 'package:syncrow_web/utils/style.dart'; import 'package:syncrow_web/utils/style.dart';
@ -23,6 +25,7 @@ class _AnalyticsEnergyManagementViewState
void initState() { void initState() {
_loadEnergyConsumptionByPhases(); _loadEnergyConsumptionByPhases();
_loadTotalEnergyConsumption(); _loadTotalEnergyConsumption();
_loadEnergyConsumptionPerDevice();
super.initState(); super.initState();
} }
@ -40,6 +43,14 @@ class _AnalyticsEnergyManagementViewState
); );
} }
void _loadEnergyConsumptionPerDevice() {
const param = GetEnergyConsumptionPerDeviceParam();
context.read<EnergyConsumptionPerDeviceBloc>().add(
const LoadEnergyConsumptionPerDeviceEvent(param),
);
}
static const _padding = EdgeInsetsDirectional.all(32); static const _padding = EdgeInsetsDirectional.all(32);
@override @override

View File

@ -1,9 +1,12 @@
import 'package:fl_chart/fl_chart.dart'; import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:syncrow_web/pages/analytics/models/device_energy_data_model.dart';
import 'package:syncrow_web/pages/analytics/modules/energy_management/helpers/energy_management_charts_helper.dart'; import 'package:syncrow_web/pages/analytics/modules/energy_management/helpers/energy_management_charts_helper.dart';
class EnergyConsumptionPerDeviceChart extends StatelessWidget { class EnergyConsumptionPerDeviceChart extends StatelessWidget {
const EnergyConsumptionPerDeviceChart({super.key}); const EnergyConsumptionPerDeviceChart({super.key, required this.chartData});
final List<DeviceEnergyDataModel> chartData;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -16,20 +19,19 @@ class EnergyConsumptionPerDeviceChart extends StatelessWidget {
gridData: EnergyManagementChartsHelper.gridData(), gridData: EnergyManagementChartsHelper.gridData(),
borderData: EnergyManagementChartsHelper.borderData(), borderData: EnergyManagementChartsHelper.borderData(),
lineTouchData: EnergyManagementChartsHelper.lineTouchData(), lineTouchData: EnergyManagementChartsHelper.lineTouchData(),
lineBarsData: [ lineBarsData: chartData.map((e) {
_buildChartBar( return _buildChartBar(
spots: [ color: e.color,
for (var i = 0; i < 12; i++) FlSpot(i.toDouble(), (i + 1) * 100), spots: e.energy
], .map(
color: Colors.amber, (energy) => FlSpot(
), energy.date.month.toDouble(),
_buildChartBar( energy.value,
color: Colors.red, ),
spots: [ )
for (var i = 0; i < 12; i++) FlSpot(i.toDouble(), (i + 1) * 125), .toList(),
], );
), }).toList(),
],
), ),
duration: Durations.extralong1, duration: Durations.extralong1,
curve: Curves.easeIn, curve: Curves.easeIn,

View File

@ -1,4 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/analytics/modules/energy_management/blocs/energy_consumption_per_device/energy_consumption_per_device_bloc.dart';
import 'package:syncrow_web/pages/analytics/modules/energy_management/widgets/chart_title.dart'; import 'package:syncrow_web/pages/analytics/modules/energy_management/widgets/chart_title.dart';
import 'package:syncrow_web/pages/analytics/modules/energy_management/widgets/energy_consumption_per_device_chart.dart'; import 'package:syncrow_web/pages/analytics/modules/energy_management/widgets/energy_consumption_per_device_chart.dart';
import 'package:syncrow_web/pages/analytics/modules/energy_management/widgets/energy_consumption_per_device_devices_list.dart'; import 'package:syncrow_web/pages/analytics/modules/energy_management/widgets/energy_consumption_per_device_devices_list.dart';
@ -9,36 +11,48 @@ class EnergyConsumptionPerDeviceChartBox extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return BlocBuilder<EnergyConsumptionPerDeviceBloc,
decoration: subSectionContainerDecoration.copyWith( EnergyConsumptionPerDeviceState>(
borderRadius: BorderRadius.circular(30), builder: (context, state) {
), return Container(
padding: const EdgeInsets.all(30), decoration: subSectionContainerDecoration.copyWith(
child: const Column( borderRadius: BorderRadius.circular(30),
spacing: 20, ),
crossAxisAlignment: CrossAxisAlignment.start, padding: const EdgeInsets.all(30),
children: [ child: Column(
Row( spacing: 20,
spacing: 32, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Expanded( Row(
flex: 3, spacing: 32,
child: FittedBox( children: [
fit: BoxFit.scaleDown, const Expanded(
alignment: AlignmentDirectional.centerStart, flex: 3,
child: ChartTitle( child: FittedBox(
title: Text('Energy Consumption per Device'), fit: BoxFit.scaleDown,
alignment: AlignmentDirectional.centerStart,
child: ChartTitle(
title: Text('Energy Consumption per Device'),
),
),
), ),
), const Spacer(),
Expanded(
flex: 2,
child: EnergyConsumptionPerDeviceDevicesList(
chartData: state.chartData,
),
),
],
),
const Divider(height: 0),
Expanded(
child: EnergyConsumptionPerDeviceChart(chartData: state.chartData),
), ),
Spacer(),
Expanded(flex: 2, child: EnergyConsumptionPerDeviceDevicesList()),
], ],
), ),
Divider(height: 0), );
Expanded(child: EnergyConsumptionPerDeviceChart()), },
],
),
); );
} }
} }

View File

@ -1,8 +1,11 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:syncrow_web/pages/analytics/models/device_energy_data_model.dart';
import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
class EnergyConsumptionPerDeviceDevicesList extends StatelessWidget { class EnergyConsumptionPerDeviceDevicesList extends StatelessWidget {
const EnergyConsumptionPerDeviceDevicesList({super.key}); const EnergyConsumptionPerDeviceDevicesList({required this.chartData, super.key});
final List<DeviceEnergyDataModel> chartData;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -13,15 +16,12 @@ class EnergyConsumptionPerDeviceDevicesList extends StatelessWidget {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end,
children: List.generate( children: chartData.map((e) => _buildDeviceCell(context, e)).toList(),
20,
(index) => _buildDeviceCell(context, index),
).toList(),
), ),
); );
} }
Widget _buildDeviceCell(BuildContext context, int index) { Widget _buildDeviceCell(BuildContext context, DeviceEnergyDataModel device) {
return Container( return Container(
height: MediaQuery.sizeOf(context).height * 0.035, height: MediaQuery.sizeOf(context).height * 0.035,
padding: const EdgeInsetsDirectional.symmetric( padding: const EdgeInsetsDirectional.symmetric(
@ -41,12 +41,12 @@ class EnergyConsumptionPerDeviceDevicesList extends StatelessWidget {
child: Row( child: Row(
spacing: 6, spacing: 6,
children: [ children: [
const CircleAvatar( CircleAvatar(
radius: 4, radius: 4,
backgroundColor: Colors.purple, backgroundColor: device.color,
), ),
Text( Text(
'Device ${index + 1}', device.deviceName,
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: const TextStyle( style: const TextStyle(
color: ColorsManager.blackColor, color: ColorsManager.blackColor,

View File

@ -1,3 +1,5 @@
import 'dart:math' as math show Random;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:syncrow_web/pages/analytics/models/device_energy_data_model.dart'; import 'package:syncrow_web/pages/analytics/models/device_energy_data_model.dart';
import 'package:syncrow_web/pages/analytics/models/energy_data_model.dart'; import 'package:syncrow_web/pages/analytics/models/energy_data_model.dart';
@ -5,40 +7,67 @@ import 'package:syncrow_web/pages/analytics/params/get_energy_consumption_per_de
import 'package:syncrow_web/pages/analytics/services/energy_consumption_per_device/energy_consumption_per_device_service.dart'; import 'package:syncrow_web/pages/analytics/services/energy_consumption_per_device/energy_consumption_per_device_service.dart';
class FakeEnergyConsumptionPerDeviceService class FakeEnergyConsumptionPerDeviceService
implements EnergyConsumptionPerDeviceService { implements EnergyConsumptionPerDeviceService {
@override @override
Future<List<DeviceEnergyDataModel>> load( Future<List<DeviceEnergyDataModel>> load(
GetEnergyConsumptionPerDeviceParam param, GetEnergyConsumptionPerDeviceParam param,
) { ) {
return Future.delayed(const Duration(milliseconds: 500), () { return Future.delayed(const Duration(milliseconds: 500), () {
return [ final random = math.Random();
DeviceEnergyDataModel( return [
color: Colors.redAccent, DeviceEnergyDataModel(
energy: List.generate(12, (i) => i) color: Colors.purpleAccent,
.map( energy: List.generate(12, (i) => i)
(index) => EnergyDataModel( .map(
date: DateTime.now().subtract(Duration(days: index)), (index) => EnergyDataModel(
value: (index + 1) * 125, date: DateTime(DateTime.now().year, index + 1, 1),
), value: random.nextInt(1450) + 50,
)
.toList(),
deviceName: 'Device 1',
deviceId: 'device_!',
), ),
DeviceEnergyDataModel( )
color: Colors.blueAccent, .toList(),
energy: List.generate(12, (i) => i) deviceName: 'Device 1',
.map( deviceId: 'device_1',
(index) => EnergyDataModel( ),
date: DateTime.now().subtract(Duration(days: index)), DeviceEnergyDataModel(
value: (index + 1) * 125, color: Colors.amberAccent,
), energy: List.generate(12, (i) => i)
) .map(
.toList(), (index) => EnergyDataModel(
deviceName: 'Device 2', date: DateTime(DateTime.now().year, index + 1, 1),
deviceId: 'device_2', value: random.nextInt(1400) + 100,
), ),
]; )
}); .toList(),
deviceName: 'Device 2',
deviceId: 'device_2',
),
DeviceEnergyDataModel(
color: Colors.redAccent,
energy: List.generate(12, (i) => i)
.map(
(index) => EnergyDataModel(
date: DateTime(DateTime.now().year, index + 1, 1),
value: random.nextInt(1480) + 20,
),
)
.toList(),
deviceName: 'Device 3',
deviceId: 'device_3',
),
DeviceEnergyDataModel(
color: Colors.blueAccent,
energy: List.generate(12, (i) => i)
.map(
(index) => EnergyDataModel(
date: DateTime(DateTime.now().year, index + 1, 1),
value: random.nextInt(1300) + 200,
),
)
.toList(),
deviceName: 'Device 4',
deviceId: 'device_4',
),
];
});
} }
} }