From fc330d6e172678f5724bef3b3e283480257dfca4 Mon Sep 17 00:00:00 2001 From: Faris Armoush Date: Wed, 28 May 2025 09:32:58 +0300 Subject: [PATCH] Making good progress towards finalizing the end side bar. --- .../air_quality/views/air_quality_view.dart | 2 +- .../air_quality_end_side_gauge_and_info.dart | 77 +++++++++++ .../air_quality_end_side_live_indicator.dart | 40 ++++++ .../widgets/air_quality_end_side_widget.dart | 128 +++++++++++++----- .../widgets/aqi_location_info_cell.dart | 40 +++--- .../widgets/aqi_sub_value_widget.dart | 30 ++-- 6 files changed, 248 insertions(+), 69 deletions(-) create mode 100644 lib/pages/analytics/modules/air_quality/widgets/air_quality_end_side_gauge_and_info.dart create mode 100644 lib/pages/analytics/modules/air_quality/widgets/air_quality_end_side_live_indicator.dart diff --git a/lib/pages/analytics/modules/air_quality/views/air_quality_view.dart b/lib/pages/analytics/modules/air_quality/views/air_quality_view.dart index 85028636..b4ae5f1b 100644 --- a/lib/pages/analytics/modules/air_quality/views/air_quality_view.dart +++ b/lib/pages/analytics/modules/air_quality/views/air_quality_view.dart @@ -33,7 +33,7 @@ class AirQualityView extends StatelessWidget { return SingleChildScrollView( child: Container( padding: _padding, - height: height * 0.9, + height: height * 1.1, child: const Column( children: [ Expanded( 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 new file mode 100644 index 00000000..086eda9e --- /dev/null +++ b/lib/pages/analytics/modules/air_quality/widgets/air_quality_end_side_gauge_and_info.dart @@ -0,0 +1,77 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:syncrow_web/utils/color_manager.dart'; +import 'package:syncrow_web/utils/constants/assets.dart'; +import 'package:syncrow_web/utils/extension/build_context_x.dart'; + +class AirQualityEndSideGaugeAndInfo extends StatelessWidget { + const AirQualityEndSideGaugeAndInfo({super.key}); + + @override + Widget build(BuildContext context) { + return Expanded( + flex: 3, + child: Row( + children: [ + const Expanded(flex: 2, child: Placeholder()), + const Spacer(), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Air Quality:', + style: context.textTheme.bodySmall?.copyWith( + color: ColorsManager.textPrimaryColor, + fontWeight: FontWeight.w400, + fontSize: 14, + ), + ), + Text( + 'Perfect', + style: context.textTheme.bodySmall?.copyWith( + color: ColorsManager.green, + fontWeight: FontWeight.w400, + fontSize: 30, + ), + ), + DefaultTextStyle( + style: context.textTheme.bodySmall!.copyWith( + color: ColorsManager.textPrimaryColor, + fontWeight: FontWeight.w400, + fontSize: 12, + ), + child: Row( + children: [ + SvgPicture.asset( + Assets.aqiTemperature, + height: 12, + width: 12, + colorFilter: const ColorFilter.mode( + ColorsManager.goodGreen, + BlendMode.srcIn, + ), + ), + const SizedBox(width: 4), + const Text('30C'), + const SizedBox(width: 10), + SvgPicture.asset( + Assets.aqiHumidity, + height: 12, + width: 12, + colorFilter: const ColorFilter.mode( + ColorsManager.textPrimaryColor, + BlendMode.srcIn, + ), + ), + const SizedBox(width: 4), + const Text('30%'), + ], + ), + ), + ], + ), + ], + ), + ); + } +} diff --git a/lib/pages/analytics/modules/air_quality/widgets/air_quality_end_side_live_indicator.dart b/lib/pages/analytics/modules/air_quality/widgets/air_quality_end_side_live_indicator.dart new file mode 100644 index 00000000..da8dd86a --- /dev/null +++ b/lib/pages/analytics/modules/air_quality/widgets/air_quality_end_side_live_indicator.dart @@ -0,0 +1,40 @@ +import 'package:flutter/material.dart'; +import 'package:syncrow_web/utils/color_manager.dart'; +import 'package:syncrow_web/utils/extension/build_context_x.dart'; + +class AirQualityEndSideLiveIndicator extends StatelessWidget { + const AirQualityEndSideLiveIndicator({super.key}); + + @override + Widget build(BuildContext context) { + return Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + 'Entrance', + style: context.textTheme.bodySmall?.copyWith( + color: ColorsManager.textPrimaryColor, + fontWeight: FontWeight.w400, + fontSize: 14, + ), + ), + const Spacer(), + CircleAvatar( + backgroundColor: ColorsManager.green.withValues( + alpha: 0.5, + ), + radius: 2, + ), + const SizedBox(width: 4), + Text( + 'Live', + style: context.textTheme.bodySmall?.copyWith( + color: ColorsManager.green.withValues(alpha: 0.5), + fontWeight: FontWeight.w400, + fontSize: 8, + ), + ), + ], + ); + } +} 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 0a91fc49..03044e8d 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,10 +1,16 @@ 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_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/analytics/blocs/analytics_devices/analytics_devices_bloc.dart'; import 'package:syncrow_web/pages/analytics/modules/energy_management/helpers/fetch_energy_management_data_helper.dart'; import 'package:syncrow_web/pages/analytics/modules/energy_management/widgets/analytics_device_dropdown.dart'; import 'package:syncrow_web/utils/color_manager.dart'; +import 'package:syncrow_web/utils/constants/assets.dart'; import 'package:syncrow_web/utils/extension/build_context_x.dart'; import 'package:syncrow_web/utils/style.dart'; @@ -41,43 +47,93 @@ class AirQualityEndSideWidget extends StatelessWidget { ), ), const Divider(), - Container( - decoration: secondarySection.copyWith(boxShadow: const []), - padding: const EdgeInsetsDirectional.all(20), - child: const Column( - spacing: 6, - children: [ - AqiSubValueWidget( - label: 'PM2.5', - value: 19, - unit: 'µg/m³', + 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), + // The spaces added to the labels are for alignment purposes, because FittedBox is used to align the text. + 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, + ), + ], ), - AqiSubValueWidget( - label: 'PM10', - value: 42, - unit: 'µg/m³', - ), - AqiSubValueWidget( - label: 'CO2', - value: 610, - unit: 'ppm', - ), - AqiSubValueWidget( - label: 'VOC', - value: 1, - unit: 'mg/m³', - ), - AqiSubValueWidget( - label: 'O3', - value: 55, - unit: 'µg/m³', - ), - AqiSubValueWidget( - label: 'NO2', - value: 18, - unit: 'µg/m³', - ), - ], + ), + ), + ), + 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, + ), + ], + ), + ), + ], + ), ), ), ], diff --git a/lib/pages/analytics/modules/air_quality/widgets/aqi_location_info_cell.dart b/lib/pages/analytics/modules/air_quality/widgets/aqi_location_info_cell.dart index b5cc000b..07c27f04 100644 --- a/lib/pages/analytics/modules/air_quality/widgets/aqi_location_info_cell.dart +++ b/lib/pages/analytics/modules/air_quality/widgets/aqi_location_info_cell.dart @@ -17,6 +17,7 @@ class AqiLocationInfoCell extends StatelessWidget { @override Widget build(BuildContext context) { + final isMediumOrLess = MediaQuery.sizeOf(context).width <= 900; return Expanded( child: Container( decoration: BoxDecoration( @@ -27,14 +28,18 @@ class AqiLocationInfoCell extends StatelessWidget { children: [ Align( alignment: AlignmentDirectional.topStart, - child: Padding( - padding: const EdgeInsetsDirectional.all(10), - child: Text( - label, - style: context.textTheme.bodySmall?.copyWith( - color: ColorsManager.textPrimaryColor, - fontWeight: FontWeight.w400, - fontSize: 12, + child: FittedBox( + fit: BoxFit.scaleDown, + alignment: AlignmentDirectional.topStart, + child: Padding( + padding: const EdgeInsetsDirectional.all(10), + child: Text( + label, + style: context.textTheme.bodySmall?.copyWith( + color: ColorsManager.textPrimaryColor, + fontWeight: FontWeight.w400, + fontSize: 12, + ), ), ), ), @@ -46,12 +51,14 @@ class AqiLocationInfoCell extends StatelessWidget { const EdgeInsetsDirectional.only(start: 32), ), child: FittedBox( + fit: BoxFit.scaleDown, + alignment: AlignmentDirectional.bottomEnd, child: Text( value, style: context.textTheme.bodySmall?.copyWith( color: ColorsManager.vividBlue.withValues(alpha: 0.7), fontWeight: FontWeight.w700, - fontSize: 40, + fontSize: 24, ), ), ), @@ -60,16 +67,13 @@ class AqiLocationInfoCell extends StatelessWidget { Align( alignment: AlignmentDirectional.bottomStart, child: SizedBox.square( - dimension: 75, + dimension: isMediumOrLess + ? MediaQuery.sizeOf(context).width * 0.15 + : MediaQuery.sizeOf(context).width * 0.035, child: FittedBox( - child: SvgPicture.asset( - svgPath, - colorFilter: ColorFilter.mode( - ColorsManager.textPrimaryColor.withValues(alpha: 0.2), - BlendMode.srcIn, - ), - fit: BoxFit.scaleDown, - ), + fit: BoxFit.scaleDown, + alignment: AlignmentDirectional.bottomStart, + child: SvgPicture.asset(svgPath), ), ), ), 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 b23a32d8..6596019a 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 @@ -40,20 +40,22 @@ class AqiSubValueWidget extends StatelessWidget { @override Widget build(BuildContext context) { final activeSegment = _getActiveSegment(value); - return Container( - padding: const EdgeInsetsDirectional.all(10), - decoration: BoxDecoration( - color: ColorsManager.whiteColors, - borderRadius: BorderRadius.circular(12), - ), - child: Row( - spacing: MediaQuery.sizeOf(context).width * 0.0075, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - _buildLabel(context), - _buildSegmentedBar(activeSegment), - _buildValueAndUnit(context), - ], + return Expanded( + child: Container( + padding: const EdgeInsetsDirectional.all(10), + decoration: BoxDecoration( + color: ColorsManager.whiteColors, + borderRadius: BorderRadius.circular(12), + ), + child: Row( + spacing: MediaQuery.sizeOf(context).width * 0.0075, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + _buildLabel(context), + _buildSegmentedBar(activeSegment), + _buildValueAndUnit(context), + ], + ), ), ); }