mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-10 15:17:31 +00:00
Extracted big widgets into smaller ones, and integrated aqi device info with RealtimeChangesBloc
.
This commit is contained in:
@ -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,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
@ -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()),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
@ -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<Status> 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<RealtimeDeviceChangesBloc, RealtimeDeviceChangesState>(
|
||||
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,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
@ -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%'),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
@ -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,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -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),
|
||||
|
Reference in New Issue
Block a user