diff --git a/lib/pages/analytics/modules/air_quality/widgets/air_quality_end_side_gauge_and_info.dart b/lib/pages/analytics/modules/air_quality/widgets/air_quality_end_side_gauge_and_info.dart index 06a33c26..8722ec68 100644 --- a/lib/pages/analytics/modules/air_quality/widgets/air_quality_end_side_gauge_and_info.dart +++ b/lib/pages/analytics/modules/air_quality/widgets/air_quality_end_side_gauge_and_info.dart @@ -5,7 +5,14 @@ import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/extension/build_context_x.dart'; class AirQualityEndSideGaugeAndInfo extends StatelessWidget { - const AirQualityEndSideGaugeAndInfo({super.key}); + const AirQualityEndSideGaugeAndInfo({ + super.key, + required this.temperature, + required this.humidity, + }); + + final int temperature; + final int humidity; @override Widget build(BuildContext context) { @@ -54,7 +61,10 @@ class AirQualityEndSideGaugeAndInfo extends StatelessWidget { ), ), const Spacer(), - const AqiHumidityAndTemperature(), + AqiHumidityAndTemperature( + temperature: temperature, + humidity: humidity, + ), ], ), ), diff --git a/lib/pages/analytics/modules/air_quality/widgets/air_quality_end_side_widget.dart b/lib/pages/analytics/modules/air_quality/widgets/air_quality_end_side_widget.dart index 808c3ff8..6e182e18 100644 --- a/lib/pages/analytics/modules/air_quality/widgets/air_quality_end_side_widget.dart +++ b/lib/pages/analytics/modules/air_quality/widgets/air_quality_end_side_widget.dart @@ -1,12 +1,7 @@ import 'package:flutter/material.dart'; -import 'package:syncrow_web/pages/analytics/modules/air_quality/widgets/air_quality_end_side_gauge_and_info.dart'; -import 'package:syncrow_web/pages/analytics/modules/air_quality/widgets/air_quality_end_side_live_indicator.dart'; -import 'package:syncrow_web/pages/analytics/modules/air_quality/widgets/aqi_location.dart'; -import 'package:syncrow_web/pages/analytics/modules/air_quality/widgets/aqi_location_info_cell.dart'; -import 'package:syncrow_web/pages/analytics/modules/air_quality/widgets/aqi_sub_value_widget.dart'; -import 'package:syncrow_web/pages/analytics/modules/air_quality/widgets/aqi_type_dropdown.dart'; +import 'package:syncrow_web/pages/analytics/modules/air_quality/widgets/aqi_device_info.dart'; +import 'package:syncrow_web/pages/analytics/modules/air_quality/widgets/aqi_location_info.dart'; import 'package:syncrow_web/pages/analytics/widgets/analytics_sidebar_header.dart'; -import 'package:syncrow_web/utils/constants/assets.dart'; import 'package:syncrow_web/utils/style.dart'; class AirQualityEndSideWidget extends StatelessWidget { @@ -19,98 +14,13 @@ class AirQualityEndSideWidget extends StatelessWidget { borderRadius: BorderRadius.circular(30), ), padding: const EdgeInsetsDirectional.all(32), - child: Column( + child: const Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const AnalyticsSidebarHeader(title: 'AQI Sensor'), - Expanded( - flex: 15, - child: Container( - decoration: secondarySection.copyWith(boxShadow: const []), - padding: const EdgeInsetsDirectional.all(20), - child: Expanded( - child: Column( - spacing: 6, - children: [ - const AirQualityEndSideLiveIndicator(), - const AirQualityEndSideGaugeAndInfo(), - const SizedBox(height: 20), - AqiSubValueWidget( - label: AqiType.pm25.value, - value: 19, - unit: AqiType.pm25.unit, - ), - AqiSubValueWidget( - label: AqiType.pm10.value, - value: 42, - unit: AqiType.pm10.unit, - ), - AqiSubValueWidget( - label: AqiType.co2.value, - value: 610, - unit: AqiType.co2.unit, - ), - AqiSubValueWidget( - label: AqiType.hcho.value, - value: 1, - unit: AqiType.hcho.unit, - ), - AqiSubValueWidget( - label: AqiType.tvoc.value, - value: 55, - unit: AqiType.tvoc.unit, - ), - AqiSubValueWidget( - label: AqiType.co2.value, - value: 18, - unit: AqiType.co2.unit, - ), - AqiSubValueWidget( - label: AqiType.c6h6.value, - value: 18, - unit: AqiType.c6h6.unit, - ), - ], - ), - ), - ), - ), - const SizedBox(height: 20), - Expanded( - flex: 6, - child: Container( - decoration: secondarySection.copyWith(boxShadow: const []), - padding: const EdgeInsetsDirectional.all(20), - child: const Column( - spacing: 8, - children: [ - AqiLocation(), - Expanded( - child: Row( - spacing: 8, - children: [ - AqiLocationInfoCell( - label: 'Temperature', - value: ' 25°', - svgPath: Assets.aqiTemperature, - ), - AqiLocationInfoCell( - label: 'Humidity', - value: '25%', - svgPath: Assets.aqiHumidity, - ), - AqiLocationInfoCell( - label: 'Air Quality', - value: ' 120', - svgPath: Assets.aqiAirQuality, - ), - ], - ), - ), - ], - ), - ), - ), + AnalyticsSidebarHeader(title: 'AQI Sensor'), + Expanded(flex: 15, child: AqiDeviceInfo()), + SizedBox(height: 20), + Expanded(flex: 6, child: AqiLocationInfo()), ], ), ); diff --git a/lib/pages/analytics/modules/air_quality/widgets/aqi_device_info.dart b/lib/pages/analytics/modules/air_quality/widgets/aqi_device_info.dart new file mode 100644 index 00000000..451350ac --- /dev/null +++ b/lib/pages/analytics/modules/air_quality/widgets/aqi_device_info.dart @@ -0,0 +1,100 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_web/pages/analytics/modules/air_quality/widgets/air_quality_end_side_gauge_and_info.dart'; +import 'package:syncrow_web/pages/analytics/modules/air_quality/widgets/air_quality_end_side_live_indicator.dart'; +import 'package:syncrow_web/pages/analytics/modules/air_quality/widgets/aqi_sub_value_widget.dart'; +import 'package:syncrow_web/pages/analytics/modules/air_quality/widgets/aqi_type_dropdown.dart'; +import 'package:syncrow_web/pages/analytics/modules/energy_management/blocs/realtime_device_changes/realtime_device_changes_bloc.dart'; +import 'package:syncrow_web/pages/device_managment/all_devices/models/device_status.dart'; +import 'package:syncrow_web/utils/style.dart'; + +class AqiDeviceInfo extends StatelessWidget { + const AqiDeviceInfo({super.key}); + + double _getValueForStatus( + List deviceStatusList, + String code, { + double defaultValue = 0, + }) { + try { + final foundStatus = deviceStatusList.firstWhere((e) => e.code == code); + return double.parse(foundStatus.value.toString()); + } catch (_) { + return defaultValue; + } + } + + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + final status = state.deviceStatusList; + final humidityValue = _getValueForStatus(status, 'humidity_value'); + final tempValue = _getValueForStatus(status, 'temp_current'); + final pm25Value = _getValueForStatus(status, 'pm25_value'); + final pm10Value = _getValueForStatus(status, 'pm10'); + final co2Value = _getValueForStatus(status, 'co2_value'); + final ch2oValue = _getValueForStatus(status, 'ch2o_value'); + final tvocValue = _getValueForStatus(status, 'tvoc_value'); + + return Container( + decoration: secondarySection.copyWith(boxShadow: const []), + padding: const EdgeInsetsDirectional.all(20), + child: Expanded( + child: Column( + spacing: 6, + children: [ + const AirQualityEndSideLiveIndicator(), + AirQualityEndSideGaugeAndInfo( + temperature: humidityValue.toInt(), + humidity: tempValue.toInt(), + ), + const SizedBox(height: 20), + AqiSubValueWidget( + range: (0, 999), + label: AqiType.pm25.value, + value: pm25Value < 100 + ? double.parse(pm25Value.toStringAsFixed(1).padLeft(4, '0')) + : pm25Value, + unit: AqiType.pm25.unit, + ), + AqiSubValueWidget( + range: (0, 999), + label: AqiType.pm10.value, + value: pm10Value < 100 + ? double.parse(pm10Value.toStringAsFixed(1).padLeft(4, '0')) + : pm10Value, + unit: AqiType.pm10.unit, + ), + AqiSubValueWidget( + range: (0, 5), + label: AqiType.hcho.value, + value: double.parse(ch2oValue.toStringAsFixed(2)), + unit: AqiType.hcho.unit, + ), + AqiSubValueWidget( + range: (0, 9.99), + label: AqiType.tvoc.value, + value: tvocValue, + unit: AqiType.tvoc.unit, + ), + AqiSubValueWidget( + range: (0, 5000), + label: AqiType.co2.value, + value: co2Value, + unit: AqiType.co2.unit, + ), + AqiSubValueWidget( + range: (0, 100), + label: AqiType.c6h6.value, + value: 18, + unit: AqiType.c6h6.unit, + ), + ], + ), + ), + ); + }, + ); + } +} diff --git a/lib/pages/analytics/modules/air_quality/widgets/aqi_humidity_and_temperature.dart b/lib/pages/analytics/modules/air_quality/widgets/aqi_humidity_and_temperature.dart index e8a3f7b4..6bea1db9 100644 --- a/lib/pages/analytics/modules/air_quality/widgets/aqi_humidity_and_temperature.dart +++ b/lib/pages/analytics/modules/air_quality/widgets/aqi_humidity_and_temperature.dart @@ -5,7 +5,13 @@ import 'package:syncrow_web/utils/constants/assets.dart'; import 'package:syncrow_web/utils/extension/build_context_x.dart'; class AqiHumidityAndTemperature extends StatelessWidget { - const AqiHumidityAndTemperature({super.key}); + const AqiHumidityAndTemperature({ + super.key, + required this.temperature, + required this.humidity, + }); + final int temperature; + final int humidity; static const iconSize = 12.0; static const colorFilter = ColorFilter.mode( @@ -13,6 +19,7 @@ class AqiHumidityAndTemperature extends StatelessWidget { BlendMode.srcIn, ); + @override Widget build(BuildContext context) { return FittedBox( @@ -33,7 +40,7 @@ class AqiHumidityAndTemperature extends StatelessWidget { colorFilter: colorFilter, ), const SizedBox(width: 4), - const Text('30°C'), + Text('$temperature°C'), const SizedBox(width: 10), SvgPicture.asset( Assets.humidityAqiSidebar, @@ -42,7 +49,7 @@ class AqiHumidityAndTemperature extends StatelessWidget { colorFilter: colorFilter, ), const SizedBox(width: 4), - const Text('30°C'), + Text('$humidity%'), ], ), ), diff --git a/lib/pages/analytics/modules/air_quality/widgets/aqi_location_info.dart b/lib/pages/analytics/modules/air_quality/widgets/aqi_location_info.dart new file mode 100644 index 00000000..f8e087b8 --- /dev/null +++ b/lib/pages/analytics/modules/air_quality/widgets/aqi_location_info.dart @@ -0,0 +1,45 @@ +import 'package:flutter/material.dart'; +import 'package:syncrow_web/pages/analytics/modules/air_quality/widgets/aqi_location.dart'; +import 'package:syncrow_web/pages/analytics/modules/air_quality/widgets/aqi_location_info_cell.dart'; +import 'package:syncrow_web/utils/constants/assets.dart'; +import 'package:syncrow_web/utils/style.dart'; + +class AqiLocationInfo extends StatelessWidget { + const AqiLocationInfo({super.key}); + + @override + Widget build(BuildContext context) { + return Container( + decoration: secondarySection.copyWith(boxShadow: const []), + padding: const EdgeInsetsDirectional.all(20), + child: const Column( + spacing: 8, + children: [ + AqiLocation(), + Expanded( + child: Row( + spacing: 8, + children: [ + AqiLocationInfoCell( + label: 'Temperature', + value: ' 25°', + svgPath: Assets.aqiTemperature, + ), + AqiLocationInfoCell( + label: 'Humidity', + value: '25%', + svgPath: Assets.aqiHumidity, + ), + AqiLocationInfoCell( + label: 'Air Quality', + value: ' 120', + svgPath: Assets.aqiAirQuality, + ), + ], + ), + ), + ], + ), + ); + } +} diff --git a/lib/pages/analytics/modules/air_quality/widgets/aqi_sub_value_widget.dart b/lib/pages/analytics/modules/air_quality/widgets/aqi_sub_value_widget.dart index 6596019a..214a4d61 100644 --- a/lib/pages/analytics/modules/air_quality/widgets/aqi_sub_value_widget.dart +++ b/lib/pages/analytics/modules/air_quality/widgets/aqi_sub_value_widget.dart @@ -5,7 +5,7 @@ import 'package:syncrow_web/utils/extension/build_context_x.dart'; final class _AqiRange { const _AqiRange({required this.max, required this.color}); - final int max; + final double max; final Color color; } @@ -14,12 +14,35 @@ class AqiSubValueWidget extends StatelessWidget { required this.label, required this.value, required this.unit, + required this.range, super.key, }); + static List<_AqiRange> _getRangesForValue((double min, double max) range) { + final (double min, double max) = range; + final rangeSize = (max - min) / 6; + return [ + _AqiRange(max: range.$1 + rangeSize, color: ColorsManager.goodGreen), + _AqiRange(max: range.$1 + (rangeSize * 2), color: ColorsManager.poorOrange), + _AqiRange(max: range.$1 + (rangeSize * 3), color: ColorsManager.poorOrange), + _AqiRange(max: range.$1 + (rangeSize * 4), color: ColorsManager.unhealthyRed), + _AqiRange(max: range.$1 + (rangeSize * 5), color: ColorsManager.severePink), + _AqiRange(max: range.$2, color: ColorsManager.hazardousPurple), + ]; + } + + int _getActiveSegmentByRange(double value, (double min, double max) range) { + final ranges = _getRangesForValue(range); + for (int i = 0; i < ranges.length; i++) { + if (value <= ranges[i].max) return i; + } + return ranges.length - 1; + } + final String label; - final int value; + final double value; final String unit; + final (double min, double max) range; static const List<_AqiRange> _ranges = [ _AqiRange(max: 12, color: ColorsManager.goodGreen), @@ -30,16 +53,9 @@ class AqiSubValueWidget extends StatelessWidget { _AqiRange(max: 500, color: ColorsManager.hazardousPurple), ]; - int _getActiveSegment(int value) { - for (int i = 0; i < _ranges.length; i++) { - if (value <= _ranges[i].max) return i; - } - return _ranges.length - 1; - } - @override Widget build(BuildContext context) { - final activeSegment = _getActiveSegment(value); + final activeSegment = _getActiveSegmentByRange(value, range); return Expanded( child: Container( padding: const EdgeInsetsDirectional.all(10),