diff --git a/lib/pages/analytics/models/phases_energy_consumption.dart b/lib/pages/analytics/models/phases_energy_consumption.dart new file mode 100644 index 00000000..0743282c --- /dev/null +++ b/lib/pages/analytics/models/phases_energy_consumption.dart @@ -0,0 +1,13 @@ +class PhasesEnergyConsumption { + final int month; + final double phaseA; + final double phaseB; + final double phaseC; + + const PhasesEnergyConsumption({ + required this.month, + required this.phaseA, + required this.phaseB, + required this.phaseC, + }); +} diff --git a/lib/pages/analytics/modules/energy_management/helpers/energy_consumption_by_phases_chart_helper.dart b/lib/pages/analytics/modules/energy_management/helpers/energy_consumption_by_phases_chart_helper.dart new file mode 100644 index 00000000..e79fe48d --- /dev/null +++ b/lib/pages/analytics/modules/energy_management/helpers/energy_consumption_by_phases_chart_helper.dart @@ -0,0 +1,20 @@ +import 'package:syncrow_web/pages/analytics/models/phases_energy_consumption.dart'; + +abstract final class EnergyConsumptionByPhasesChartHelper { + const EnergyConsumptionByPhasesChartHelper._(); + + static const fakeData = [ + PhasesEnergyConsumption(month: 1, phaseA: 200, phaseB: 300, phaseC: 400), + PhasesEnergyConsumption(month: 2, phaseA: 300, phaseB: 400, phaseC: 500), + PhasesEnergyConsumption(month: 3, phaseA: 400, phaseB: 500, phaseC: 600), + PhasesEnergyConsumption(month: 4, phaseA: 100, phaseB: 100, phaseC: 100), + PhasesEnergyConsumption(month: 5, phaseA: 300, phaseB: 400, phaseC: 500), + PhasesEnergyConsumption(month: 6, phaseA: 300, phaseB: 100, phaseC: 400), + PhasesEnergyConsumption(month: 7, phaseA: 300, phaseB: 100, phaseC: 400), + PhasesEnergyConsumption(month: 8, phaseA: 500, phaseB: 100, phaseC: 100), + PhasesEnergyConsumption(month: 9, phaseA: 500, phaseB: 100, phaseC: 200), + PhasesEnergyConsumption(month: 10, phaseA: 100, phaseB: 50, phaseC: 50), + PhasesEnergyConsumption(month: 11, phaseA: 600, phaseB: 750, phaseC: 130), + PhasesEnergyConsumption(month: 12, phaseA: 100, phaseB: 80, phaseC: 100), + ]; +} diff --git a/lib/pages/analytics/modules/energy_management/helpers/energy_management_charts_helper.dart b/lib/pages/analytics/modules/energy_management/helpers/energy_management_charts_helper.dart index 851569a2..bc60cc39 100644 --- a/lib/pages/analytics/modules/energy_management/helpers/energy_management_charts_helper.dart +++ b/lib/pages/analytics/modules/energy_management/helpers/energy_management_charts_helper.dart @@ -39,6 +39,7 @@ abstract final class EnergyManagementChartsHelper { getTitlesWidget: (value, meta) => Padding( padding: const EdgeInsetsDirectional.only(end: 12), child: FittedBox( + alignment: AlignmentDirectional.centerStart, fit: BoxFit.scaleDown, child: Text( value.formatNumberToKwh, diff --git a/lib/pages/analytics/modules/energy_management/widgets/energy_consumption_by_phases_chart.dart b/lib/pages/analytics/modules/energy_management/widgets/energy_consumption_by_phases_chart.dart new file mode 100644 index 00000000..db131a21 --- /dev/null +++ b/lib/pages/analytics/modules/energy_management/widgets/energy_consumption_by_phases_chart.dart @@ -0,0 +1,169 @@ +import 'package:fl_chart/fl_chart.dart'; +import 'package:flutter/material.dart'; +import 'package:syncrow_web/pages/analytics/helpers/get_month_name_from_int.dart'; +import 'package:syncrow_web/pages/analytics/models/phases_energy_consumption.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/extension/build_context_x.dart'; + +class EnergyConsumptionByPhasesChart extends StatelessWidget { + const EnergyConsumptionByPhasesChart({ + super.key, + required this.energyData, + }); + + final List energyData; + + @override + Widget build(BuildContext context) { + return BarChart( + BarChartData( + gridData: EnergyManagementChartsHelper.gridData(), + borderData: EnergyManagementChartsHelper.borderData(), + barTouchData: _barTouchData(context), + titlesData: _titlesData(context), + barGroups: energyData.asMap().entries.map((entry) { + final index = entry.key; + final data = entry.value; + + return BarChartGroupData( + x: index, + barRods: [ + BarChartRodData( + color: ColorsManager.vividBlue.withValues(alpha: 0.1), + toY: data.phaseA + data.phaseB + data.phaseC, + rodStackItems: [ + BarChartRodStackItem( + 0, + data.phaseA, + ColorsManager.vividBlue.withValues(alpha: 0.8), + ), + BarChartRodStackItem( + data.phaseA, + data.phaseA + data.phaseB, + ColorsManager.vividBlue.withValues(alpha: 0.4), + ), + BarChartRodStackItem( + data.phaseA + data.phaseB, + data.phaseA + data.phaseB + data.phaseC, + ColorsManager.vividBlue.withValues(alpha: 0.15), + ), + ], + width: 16, + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(8), + topRight: Radius.circular(8), + ), + ), + ], + ); + }).toList(), + ), + ); + } + + BarTouchData _barTouchData(BuildContext context) { + return BarTouchData( + touchTooltipData: BarTouchTooltipData( + getTooltipColor: (touchTooltipItem) => ColorsManager.whiteColors, + tooltipBorder: const BorderSide( + color: ColorsManager.semiTransparentBlack, + ), + tooltipRoundedRadius: 16, + tooltipPadding: const EdgeInsets.all(8), + getTooltipItem: (group, groupIndex, rod, rodIndex) => getTooltipItem( + context: context, + group: group, + groupIndex: groupIndex, + rod: rod, + rodIndex: rodIndex, + ), + ), + ); + } + + BarTooltipItem? getTooltipItem({ + required BuildContext context, + required BarChartGroupData group, + required int groupIndex, + required BarChartRodData rod, + required int rodIndex, + }) { + final data = energyData; + + final month = data[group.x.toInt()].month.getMonthName; + final phaseA = data[group.x.toInt()].phaseA; + final phaseB = data[group.x.toInt()].phaseB; + final phaseC = data[group.x.toInt()].phaseC; + + return BarTooltipItem( + '$month\n', + context.textTheme.bodyMedium!.copyWith( + color: ColorsManager.blackColor, + fontSize: 14, + ), + children: [ + TextSpan( + text: 'Phase A: $phaseA\n', + style: context.textTheme.bodySmall?.copyWith( + color: ColorsManager.blackColor, + fontSize: 12, + ), + ), + TextSpan( + text: 'Phase B: $phaseB\n', + style: context.textTheme.bodySmall?.copyWith( + color: ColorsManager.blackColor, + fontSize: 12, + ), + ), + TextSpan( + text: 'Phase C: $phaseC', + style: context.textTheme.bodySmall?.copyWith( + color: ColorsManager.blackColor, + fontSize: 12, + ), + ), + ], + ); + } + + FlTitlesData _titlesData(BuildContext context) { + final titlesData = EnergyManagementChartsHelper.titlesData(context); + + final leftTitles = titlesData.leftTitles.copyWith( + sideTitles: titlesData.leftTitles.sideTitles.copyWith( + reservedSize: 70, + ), + ); + + final bottomTitles = AxisTitles( + sideTitles: SideTitles( + showTitles: true, + getTitlesWidget: (value, _) { + final month = energyData[value.toInt()].month.getMonthName; + return FittedBox( + alignment: AlignmentDirectional.bottomCenter, + fit: BoxFit.scaleDown, + child: RotatedBox( + quarterTurns: 3, + child: Text( + month, + style: context.textTheme.bodySmall?.copyWith( + color: ColorsManager.greyColor, + fontSize: 11, + ), + ), + ), + ); + }, + reservedSize: 36, + ), + ); + + return titlesData.copyWith( + leftTitles: leftTitles, + bottomTitles: bottomTitles, + ); + } +} diff --git a/lib/pages/analytics/modules/energy_management/widgets/energy_consumption_by_phases_chart_box.dart b/lib/pages/analytics/modules/energy_management/widgets/energy_consumption_by_phases_chart_box.dart index 76d4c6ff..58ca6e68 100644 --- a/lib/pages/analytics/modules/energy_management/widgets/energy_consumption_by_phases_chart_box.dart +++ b/lib/pages/analytics/modules/energy_management/widgets/energy_consumption_by_phases_chart_box.dart @@ -1,5 +1,7 @@ import 'package:flutter/material.dart'; +import 'package:syncrow_web/pages/analytics/modules/energy_management/helpers/energy_consumption_by_phases_chart_helper.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_by_phases_chart.dart'; import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/extension/build_context_x.dart'; import 'package:syncrow_web/utils/style.dart'; @@ -14,6 +16,7 @@ class EnergyConsumptionByPhasesChartBox extends StatelessWidget { decoration: secondarySection, child: Column( mainAxisSize: MainAxisSize.min, + spacing: 20, children: [ Row( crossAxisAlignment: CrossAxisAlignment.center, @@ -43,6 +46,11 @@ class EnergyConsumptionByPhasesChartBox extends StatelessWidget { ].map((phase) => _buildPhaseCell(context, phase)), ], ), + const Expanded( + child: EnergyConsumptionByPhasesChart( + energyData: EnergyConsumptionByPhasesChartHelper.fakeData, + ), + ), ], ), );