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_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_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/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/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_per_device_param.dart';
import 'package:syncrow_web/pages/analytics/params/get_total_energy_consumption_param.dart';
import 'package:syncrow_web/utils/style.dart';
@ -23,6 +25,7 @@ class _AnalyticsEnergyManagementViewState
void initState() {
_loadEnergyConsumptionByPhases();
_loadTotalEnergyConsumption();
_loadEnergyConsumptionPerDevice();
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);
@override

View File

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

View File

@ -1,4 +1,6 @@
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/energy_consumption_per_device_chart.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
Widget build(BuildContext context) {
return Container(
decoration: subSectionContainerDecoration.copyWith(
borderRadius: BorderRadius.circular(30),
),
padding: const EdgeInsets.all(30),
child: const Column(
spacing: 20,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
spacing: 32,
return BlocBuilder<EnergyConsumptionPerDeviceBloc,
EnergyConsumptionPerDeviceState>(
builder: (context, state) {
return Container(
decoration: subSectionContainerDecoration.copyWith(
borderRadius: BorderRadius.circular(30),
),
padding: const EdgeInsets.all(30),
child: Column(
spacing: 20,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
flex: 3,
child: FittedBox(
fit: BoxFit.scaleDown,
alignment: AlignmentDirectional.centerStart,
child: ChartTitle(
title: Text('Energy Consumption per Device'),
Row(
spacing: 32,
children: [
const Expanded(
flex: 3,
child: FittedBox(
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:syncrow_web/pages/analytics/models/device_energy_data_model.dart';
import 'package:syncrow_web/utils/color_manager.dart';
class EnergyConsumptionPerDeviceDevicesList extends StatelessWidget {
const EnergyConsumptionPerDeviceDevicesList({super.key});
const EnergyConsumptionPerDeviceDevicesList({required this.chartData, super.key});
final List<DeviceEnergyDataModel> chartData;
@override
Widget build(BuildContext context) {
@ -13,15 +16,12 @@ class EnergyConsumptionPerDeviceDevicesList extends StatelessWidget {
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.end,
children: List.generate(
20,
(index) => _buildDeviceCell(context, index),
).toList(),
children: chartData.map((e) => _buildDeviceCell(context, e)).toList(),
),
);
}
Widget _buildDeviceCell(BuildContext context, int index) {
Widget _buildDeviceCell(BuildContext context, DeviceEnergyDataModel device) {
return Container(
height: MediaQuery.sizeOf(context).height * 0.035,
padding: const EdgeInsetsDirectional.symmetric(
@ -41,12 +41,12 @@ class EnergyConsumptionPerDeviceDevicesList extends StatelessWidget {
child: Row(
spacing: 6,
children: [
const CircleAvatar(
CircleAvatar(
radius: 4,
backgroundColor: Colors.purple,
backgroundColor: device.color,
),
Text(
'Device ${index + 1}',
device.deviceName,
textAlign: TextAlign.center,
style: const TextStyle(
color: ColorsManager.blackColor,

View File

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