mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-11 07:38:05 +00:00
Compare commits
7 Commits
SP-1509-FE
...
bugfix/cha
Author | SHA1 | Date | |
---|---|---|---|
d80f5e1f3a | |||
5279020d08 | |||
da481536c4 | |||
f21366268a | |||
c3aef736fd | |||
d45ff262c7 | |||
a9d6c6f4ee |
@ -16,7 +16,7 @@ import 'package:syncrow_web/pages/analytics/services/analytics_devices/analytics
|
|||||||
import 'package:syncrow_web/pages/analytics/services/analytics_devices/remote_energy_management_analytics_devices_service.dart';
|
import 'package:syncrow_web/pages/analytics/services/analytics_devices/remote_energy_management_analytics_devices_service.dart';
|
||||||
import 'package:syncrow_web/pages/analytics/services/analytics_devices/remote_occupancy_analytics_devices_service.dart';
|
import 'package:syncrow_web/pages/analytics/services/analytics_devices/remote_occupancy_analytics_devices_service.dart';
|
||||||
import 'package:syncrow_web/pages/analytics/services/energy_consumption_by_phases/fake_energy_consumption_by_phases_service.dart';
|
import 'package:syncrow_web/pages/analytics/services/energy_consumption_by_phases/fake_energy_consumption_by_phases_service.dart';
|
||||||
import 'package:syncrow_web/pages/analytics/services/energy_consumption_per_device/fake_energy_consumption_per_device_service.dart';
|
import 'package:syncrow_web/pages/analytics/services/energy_consumption_per_device/remote_energy_consumption_per_device_service.dart';
|
||||||
import 'package:syncrow_web/pages/analytics/services/occupacy/fake_occupacy_service.dart';
|
import 'package:syncrow_web/pages/analytics/services/occupacy/fake_occupacy_service.dart';
|
||||||
import 'package:syncrow_web/pages/analytics/services/occupancy_heat_map/remote_occupancy_heat_map_service.dart';
|
import 'package:syncrow_web/pages/analytics/services/occupancy_heat_map/remote_occupancy_heat_map_service.dart';
|
||||||
import 'package:syncrow_web/pages/analytics/services/power_clamp_info/remote_power_clamp_info_service.dart';
|
import 'package:syncrow_web/pages/analytics/services/power_clamp_info/remote_power_clamp_info_service.dart';
|
||||||
@ -62,7 +62,7 @@ class _AnalyticsPageState extends State<AnalyticsPage> {
|
|||||||
),
|
),
|
||||||
BlocProvider(
|
BlocProvider(
|
||||||
create: (context) => EnergyConsumptionPerDeviceBloc(
|
create: (context) => EnergyConsumptionPerDeviceBloc(
|
||||||
FakeEnergyConsumptionPerDeviceService(),
|
RemoteEnergyConsumptionPerDeviceService(_httpService),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
BlocProvider(
|
BlocProvider(
|
||||||
|
@ -42,7 +42,12 @@ abstract final class FetchEnergyManagementDataHelper {
|
|||||||
spaceId: spaceId,
|
spaceId: spaceId,
|
||||||
);
|
);
|
||||||
loadEnergyConsumptionByPhases(context, selectedDate: selectedDate);
|
loadEnergyConsumptionByPhases(context, selectedDate: selectedDate);
|
||||||
loadEnergyConsumptionPerDevice(context);
|
loadEnergyConsumptionPerDevice(
|
||||||
|
context,
|
||||||
|
communityId: communityId,
|
||||||
|
spaceId: spaceId,
|
||||||
|
selectedDate: selectedDate0,
|
||||||
|
);
|
||||||
loadRealtimeDeviceChanges(context);
|
loadRealtimeDeviceChanges(context);
|
||||||
loadPowerClampInfo(context);
|
loadPowerClampInfo(context);
|
||||||
}
|
}
|
||||||
@ -76,10 +81,19 @@ abstract final class FetchEnergyManagementDataHelper {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void loadEnergyConsumptionPerDevice(BuildContext context) {
|
static void loadEnergyConsumptionPerDevice(
|
||||||
const param = GetEnergyConsumptionPerDeviceParam();
|
BuildContext context, {
|
||||||
|
DateTime? selectedDate,
|
||||||
|
required String communityId,
|
||||||
|
required String spaceId,
|
||||||
|
}) {
|
||||||
|
final param = GetEnergyConsumptionPerDeviceParam(
|
||||||
|
spaceId: spaceId,
|
||||||
|
communityId: communityId,
|
||||||
|
monthDate: selectedDate,
|
||||||
|
);
|
||||||
context.read<EnergyConsumptionPerDeviceBloc>().add(
|
context.read<EnergyConsumptionPerDeviceBloc>().add(
|
||||||
const LoadEnergyConsumptionPerDeviceEvent(param),
|
LoadEnergyConsumptionPerDeviceEvent(param),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,10 @@ class EnergyConsumptionByPhasesChart extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BarChart(
|
return BarChart(
|
||||||
BarChartData(
|
BarChartData(
|
||||||
gridData: EnergyManagementChartsHelper.gridData(),
|
gridData: EnergyManagementChartsHelper.gridData().copyWith(
|
||||||
|
checkToShowHorizontalLine: (value) => true,
|
||||||
|
horizontalInterval: 250,
|
||||||
|
),
|
||||||
borderData: EnergyManagementChartsHelper.borderData(),
|
borderData: EnergyManagementChartsHelper.borderData(),
|
||||||
barTouchData: _barTouchData(context),
|
barTouchData: _barTouchData(context),
|
||||||
titlesData: _titlesData(context),
|
titlesData: _titlesData(context),
|
||||||
|
@ -16,7 +16,10 @@ class EnergyConsumptionPerDeviceChart extends StatelessWidget {
|
|||||||
context,
|
context,
|
||||||
leftTitlesInterval: 250,
|
leftTitlesInterval: 250,
|
||||||
),
|
),
|
||||||
gridData: EnergyManagementChartsHelper.gridData(),
|
gridData: EnergyManagementChartsHelper.gridData().copyWith(
|
||||||
|
checkToShowHorizontalLine: (value) => true,
|
||||||
|
horizontalInterval: 250,
|
||||||
|
),
|
||||||
borderData: EnergyManagementChartsHelper.borderData(),
|
borderData: EnergyManagementChartsHelper.borderData(),
|
||||||
lineTouchData: EnergyManagementChartsHelper.lineTouchData(),
|
lineTouchData: EnergyManagementChartsHelper.lineTouchData(),
|
||||||
lineBarsData: chartData.map((e) {
|
lineBarsData: chartData.map((e) {
|
||||||
|
@ -4,15 +4,6 @@ import 'package:syncrow_web/pages/analytics/models/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';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
|
||||||
// energy_consumption_chart will return id, name and consumption
|
|
||||||
const phasesJson = {
|
|
||||||
"1": {
|
|
||||||
"phaseOne": 1000,
|
|
||||||
"phaseTwo": 2000,
|
|
||||||
"phaseThree": 3000,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class TotalEnergyConsumptionChart extends StatelessWidget {
|
class TotalEnergyConsumptionChart extends StatelessWidget {
|
||||||
const TotalEnergyConsumptionChart({required this.chartData, super.key});
|
const TotalEnergyConsumptionChart({required this.chartData, super.key});
|
||||||
|
|
||||||
@ -23,8 +14,14 @@ class TotalEnergyConsumptionChart extends StatelessWidget {
|
|||||||
return Expanded(
|
return Expanded(
|
||||||
child: LineChart(
|
child: LineChart(
|
||||||
LineChartData(
|
LineChartData(
|
||||||
titlesData: EnergyManagementChartsHelper.titlesData(context),
|
titlesData: EnergyManagementChartsHelper.titlesData(
|
||||||
gridData: EnergyManagementChartsHelper.gridData(),
|
context,
|
||||||
|
leftTitlesInterval: 250,
|
||||||
|
),
|
||||||
|
gridData: EnergyManagementChartsHelper.gridData().copyWith(
|
||||||
|
checkToShowHorizontalLine: (value) => true,
|
||||||
|
horizontalInterval: 250,
|
||||||
|
),
|
||||||
borderData: EnergyManagementChartsHelper.borderData(),
|
borderData: EnergyManagementChartsHelper.borderData(),
|
||||||
lineTouchData: EnergyManagementChartsHelper.lineTouchData(),
|
lineTouchData: EnergyManagementChartsHelper.lineTouchData(),
|
||||||
lineBarsData: _lineBarsData,
|
lineBarsData: _lineBarsData,
|
||||||
|
@ -0,0 +1,54 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
||||||
|
|
||||||
|
class HeatMapTooltip extends StatelessWidget {
|
||||||
|
const HeatMapTooltip({
|
||||||
|
required this.date,
|
||||||
|
required this.value,
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
final DateTime date;
|
||||||
|
final int value;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return FittedBox(
|
||||||
|
fit: BoxFit.scaleDown,
|
||||||
|
alignment: AlignmentDirectional.topStart,
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.all(8),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: ColorsManager.grey700,
|
||||||
|
borderRadius: BorderRadius.circular(3),
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
DateFormat('MMM d, yyyy').format(date),
|
||||||
|
style: context.textTheme.bodySmall?.copyWith(
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
color: ColorsManager.whiteColors,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Divider(height: 2, thickness: 1),
|
||||||
|
Text(
|
||||||
|
'$value Occupants',
|
||||||
|
style: context.textTheme.bodySmall?.copyWith(
|
||||||
|
fontSize: 10,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
color: ColorsManager.whiteColors,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,108 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:syncrow_web/pages/analytics/modules/occupancy/widgets/heat_map_tooltip.dart';
|
||||||
|
import 'package:syncrow_web/pages/analytics/modules/occupancy/widgets/occupancy_painter.dart';
|
||||||
|
|
||||||
|
class InteractiveHeatMap extends StatefulWidget {
|
||||||
|
const InteractiveHeatMap({
|
||||||
|
required this.items,
|
||||||
|
required this.maxValue,
|
||||||
|
required this.cellSize,
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
final List<OccupancyPaintItem> items;
|
||||||
|
final int maxValue;
|
||||||
|
final double cellSize;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<InteractiveHeatMap> createState() => _InteractiveHeatMapState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _InteractiveHeatMapState extends State<InteractiveHeatMap> {
|
||||||
|
OccupancyPaintItem? _hoveredItem;
|
||||||
|
OverlayEntry? _overlayEntry;
|
||||||
|
final LayerLink _layerLink = LayerLink();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_removeOverlay();
|
||||||
|
_overlayEntry?.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _removeOverlay() {
|
||||||
|
_overlayEntry?.remove();
|
||||||
|
_overlayEntry = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _showTooltip(OccupancyPaintItem item, Offset localPosition) {
|
||||||
|
_removeOverlay();
|
||||||
|
|
||||||
|
final column = item.index ~/ 7;
|
||||||
|
final row = item.index % 7;
|
||||||
|
final x = column * widget.cellSize;
|
||||||
|
final y = row * widget.cellSize;
|
||||||
|
|
||||||
|
_overlayEntry = OverlayEntry(
|
||||||
|
builder: (context) => Positioned(
|
||||||
|
child: CompositedTransformFollower(
|
||||||
|
link: _layerLink,
|
||||||
|
offset: Offset(x + widget.cellSize, y),
|
||||||
|
child: Material(
|
||||||
|
color: Colors.transparent,
|
||||||
|
child: Transform.translate(
|
||||||
|
offset: Offset(-(widget.cellSize * 2.5), -50),
|
||||||
|
child: HeatMapTooltip(date: item.date, value: item.value),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
Overlay.of(context).insert(_overlayEntry!);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return CompositedTransformTarget(
|
||||||
|
link: _layerLink,
|
||||||
|
child: MouseRegion(
|
||||||
|
onHover: (event) {
|
||||||
|
final column = event.localPosition.dx ~/ widget.cellSize;
|
||||||
|
final row = event.localPosition.dy ~/ widget.cellSize;
|
||||||
|
final index = column * 7 + row;
|
||||||
|
|
||||||
|
if (index >= 0 && index < widget.items.length) {
|
||||||
|
final item = widget.items[index];
|
||||||
|
if (_hoveredItem != item) {
|
||||||
|
setState(() => _hoveredItem = item);
|
||||||
|
_showTooltip(item, event.localPosition);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_removeOverlay();
|
||||||
|
setState(() => _hoveredItem = null);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onExit: (_) {
|
||||||
|
_removeOverlay();
|
||||||
|
setState(() => _hoveredItem = null);
|
||||||
|
},
|
||||||
|
child: CustomPaint(
|
||||||
|
isComplex: true,
|
||||||
|
size: _painterSize,
|
||||||
|
painter: OccupancyPainter(
|
||||||
|
items: widget.items,
|
||||||
|
maxValue: widget.maxValue,
|
||||||
|
hoveredItem: _hoveredItem,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Size get _painterSize {
|
||||||
|
final height = 7 * widget.cellSize;
|
||||||
|
final width = widget.items.length ~/ 7 * widget.cellSize;
|
||||||
|
return Size(width, height);
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
import 'dart:math' as math show max;
|
import 'dart:math' as math show max;
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:syncrow_web/pages/analytics/modules/occupancy/widgets/interactive_heat_map.dart';
|
||||||
import 'package:syncrow_web/pages/analytics/modules/occupancy/widgets/occupancy_heat_map_days.dart';
|
import 'package:syncrow_web/pages/analytics/modules/occupancy/widgets/occupancy_heat_map_days.dart';
|
||||||
import 'package:syncrow_web/pages/analytics/modules/occupancy/widgets/occupancy_heat_map_gradient.dart';
|
import 'package:syncrow_web/pages/analytics/modules/occupancy/widgets/occupancy_heat_map_gradient.dart';
|
||||||
import 'package:syncrow_web/pages/analytics/modules/occupancy/widgets/occupancy_heat_map_months.dart';
|
import 'package:syncrow_web/pages/analytics/modules/occupancy/widgets/occupancy_heat_map_months.dart';
|
||||||
@ -28,7 +29,7 @@ class OccupancyHeatMap extends StatelessWidget {
|
|||||||
return List.generate(_totalWeeks * 7, (index) {
|
return List.generate(_totalWeeks * 7, (index) {
|
||||||
final date = startDate.add(Duration(days: index));
|
final date = startDate.add(Duration(days: index));
|
||||||
final value = heatMapData[date] ?? 0;
|
final value = heatMapData[date] ?? 0;
|
||||||
return OccupancyPaintItem(index: index, value: value);
|
return OccupancyPaintItem(index: index, value: value, date: date);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,15 +59,13 @@ class OccupancyHeatMap extends StatelessWidget {
|
|||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
const OccupancyHeatMapDays(cellSize: _cellSize),
|
const OccupancyHeatMapDays(cellSize: _cellSize),
|
||||||
CustomPaint(
|
SizedBox(
|
||||||
size: const Size(_totalWeeks * _cellSize, 7 * _cellSize),
|
width: _totalWeeks * _cellSize,
|
||||||
child: CustomPaint(
|
height: 7 * _cellSize,
|
||||||
isComplex: true,
|
child: InteractiveHeatMap(
|
||||||
size: const Size(_totalWeeks * _cellSize, 7 * _cellSize),
|
|
||||||
painter: OccupancyPainter(
|
|
||||||
items: paintItems,
|
items: paintItems,
|
||||||
maxValue: _maxValue,
|
maxValue: _maxValue,
|
||||||
),
|
cellSize: _cellSize,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -4,18 +4,25 @@ import 'package:syncrow_web/utils/color_manager.dart';
|
|||||||
class OccupancyPaintItem {
|
class OccupancyPaintItem {
|
||||||
final int index;
|
final int index;
|
||||||
final int value;
|
final int value;
|
||||||
|
final DateTime date;
|
||||||
|
|
||||||
const OccupancyPaintItem({required this.index, required this.value});
|
const OccupancyPaintItem({
|
||||||
|
required this.index,
|
||||||
|
required this.value,
|
||||||
|
required this.date,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
class OccupancyPainter extends CustomPainter {
|
class OccupancyPainter extends CustomPainter {
|
||||||
OccupancyPainter({
|
OccupancyPainter({
|
||||||
required this.items,
|
required this.items,
|
||||||
required this.maxValue,
|
required this.maxValue,
|
||||||
|
this.hoveredItem,
|
||||||
});
|
});
|
||||||
|
|
||||||
final List<OccupancyPaintItem> items;
|
final List<OccupancyPaintItem> items;
|
||||||
final int maxValue;
|
final int maxValue;
|
||||||
|
final OccupancyPaintItem? hoveredItem;
|
||||||
|
|
||||||
static const double cellSize = 16.0;
|
static const double cellSize = 16.0;
|
||||||
|
|
||||||
@ -25,6 +32,10 @@ class OccupancyPainter extends CustomPainter {
|
|||||||
final Paint borderPaint = Paint()
|
final Paint borderPaint = Paint()
|
||||||
..color = ColorsManager.grayBorder.withValues(alpha: 0.4)
|
..color = ColorsManager.grayBorder.withValues(alpha: 0.4)
|
||||||
..style = PaintingStyle.stroke;
|
..style = PaintingStyle.stroke;
|
||||||
|
final Paint hoveredBorderPaint = Paint()
|
||||||
|
..color = Colors.black
|
||||||
|
..style = PaintingStyle.stroke
|
||||||
|
..strokeWidth = 1.5;
|
||||||
|
|
||||||
for (final item in items) {
|
for (final item in items) {
|
||||||
final column = item.index ~/ 7;
|
final column = item.index ~/ 7;
|
||||||
@ -37,6 +48,10 @@ class OccupancyPainter extends CustomPainter {
|
|||||||
final rect = Rect.fromLTWH(x, y, cellSize, cellSize);
|
final rect = Rect.fromLTWH(x, y, cellSize, cellSize);
|
||||||
canvas.drawRect(rect, fillPaint);
|
canvas.drawRect(rect, fillPaint);
|
||||||
|
|
||||||
|
// Highlight the hovered item
|
||||||
|
if (hoveredItem != null && hoveredItem!.index == item.index) {
|
||||||
|
canvas.drawRect(rect, hoveredBorderPaint);
|
||||||
|
} else {
|
||||||
_drawDashedLine(
|
_drawDashedLine(
|
||||||
canvas,
|
canvas,
|
||||||
Offset(x, y),
|
Offset(x, y),
|
||||||
@ -51,8 +66,9 @@ class OccupancyPainter extends CustomPainter {
|
|||||||
);
|
);
|
||||||
|
|
||||||
canvas.drawLine(Offset(x, y), Offset(x, y + cellSize), borderPaint);
|
canvas.drawLine(Offset(x, y), Offset(x, y + cellSize), borderPaint);
|
||||||
canvas.drawLine(
|
canvas.drawLine(Offset(x + cellSize, y), Offset(x + cellSize, y + cellSize),
|
||||||
Offset(x + cellSize, y), Offset(x + cellSize, y + cellSize), borderPaint);
|
borderPaint);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,5 +96,6 @@ class OccupancyPainter extends CustomPainter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
|
bool shouldRepaint(covariant OccupancyPainter oldDelegate) =>
|
||||||
|
oldDelegate.hoveredItem != hoveredItem;
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,19 @@
|
|||||||
class GetEnergyConsumptionPerDeviceParam {
|
class GetEnergyConsumptionPerDeviceParam {
|
||||||
const GetEnergyConsumptionPerDeviceParam();
|
const GetEnergyConsumptionPerDeviceParam({
|
||||||
|
this.monthDate,
|
||||||
|
this.spaceId,
|
||||||
|
this.communityId,
|
||||||
|
});
|
||||||
|
|
||||||
|
final DateTime? monthDate;
|
||||||
|
final String? spaceId;
|
||||||
|
final String? communityId;
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => {
|
||||||
|
'monthDate':
|
||||||
|
'${monthDate?.year}-${monthDate?.month.toString().padLeft(2, '0')}',
|
||||||
|
if (spaceId == null || spaceId == null) 'spaceUuid': spaceId,
|
||||||
|
'communityUuid': communityId,
|
||||||
|
'groupByDevice': true,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ class GetTotalEnergyConsumptionParam {
|
|||||||
return {
|
return {
|
||||||
'monthDate':
|
'monthDate':
|
||||||
'${monthDate?.year}-${monthDate?.month.toString().padLeft(2, '0')}',
|
'${monthDate?.year}-${monthDate?.month.toString().padLeft(2, '0')}',
|
||||||
if (communityId == null || communityId!.isEmpty) 'spaceUuid': spaceId,
|
if (spaceId == null || spaceId == null) 'spaceUuid': spaceId,
|
||||||
'communityUuid': communityId,
|
'communityUuid': communityId,
|
||||||
'groupByDevice': false,
|
'groupByDevice': false,
|
||||||
};
|
};
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
|
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/params/get_energy_consumption_per_device_param.dart';
|
import 'package:syncrow_web/pages/analytics/params/get_energy_consumption_per_device_param.dart';
|
||||||
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';
|
||||||
import 'package:syncrow_web/services/api/http_service.dart';
|
import 'package:syncrow_web/services/api/http_service.dart';
|
||||||
@ -15,16 +17,10 @@ class RemoteEnergyConsumptionPerDeviceService
|
|||||||
) async {
|
) async {
|
||||||
try {
|
try {
|
||||||
final response = await _httpService.get(
|
final response = await _httpService.get(
|
||||||
path: 'endpoint',
|
path: '/power-clamp/historical',
|
||||||
showServerMessage: true,
|
showServerMessage: true,
|
||||||
expectedResponseModel: (data) {
|
queryParameters: param.toJson(),
|
||||||
final json = data as Map<String, dynamic>? ?? {};
|
expectedResponseModel: _EnergyConsumptionPerDeviceMapper.map,
|
||||||
final mappedData = json['data'] as List<dynamic>? ?? [];
|
|
||||||
return mappedData.map((e) {
|
|
||||||
final jsonData = e as Map<String, dynamic>;
|
|
||||||
return DeviceEnergyDataModel.fromJson(jsonData);
|
|
||||||
}).toList();
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
return response;
|
return response;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -32,3 +28,33 @@ class RemoteEnergyConsumptionPerDeviceService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract final class _EnergyConsumptionPerDeviceMapper {
|
||||||
|
const _EnergyConsumptionPerDeviceMapper._();
|
||||||
|
static List<DeviceEnergyDataModel> map(dynamic data) {
|
||||||
|
final json = data as Map<String, dynamic>? ?? {};
|
||||||
|
final mappedData = json['data'] as List<dynamic>? ?? [];
|
||||||
|
return mappedData.where((e) {
|
||||||
|
final deviceData = (e as Map<String, dynamic>)['data'] as List<dynamic>? ?? [];
|
||||||
|
return deviceData.isNotEmpty;
|
||||||
|
}).map((e) {
|
||||||
|
final deviceData = e as Map<String, dynamic>;
|
||||||
|
final energyData = deviceData['data'] as List<dynamic>;
|
||||||
|
|
||||||
|
return DeviceEnergyDataModel(
|
||||||
|
deviceId: deviceData['deviceUuid'] as String,
|
||||||
|
deviceName: deviceData['deviceName'] as String,
|
||||||
|
color: Color((DateTime.now().microsecondsSinceEpoch +
|
||||||
|
deviceData['deviceUuid'].hashCode) |
|
||||||
|
0xFF000000),
|
||||||
|
energy: energyData.map((data) {
|
||||||
|
final energyJson = data as Map<String, dynamic>;
|
||||||
|
return EnergyDataModel(
|
||||||
|
date: DateTime.parse(energyJson['date'] as String),
|
||||||
|
value: double.parse(energyJson['total_energy_consumed_kw'] as String),
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
);
|
||||||
|
}).toList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user