mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-10 15:17:31 +00:00
Making good progress towards finalizing the end side bar.
This commit is contained in:
@ -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(
|
||||
|
@ -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%'),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -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,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
@ -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,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
@ -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),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -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),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
Reference in New Issue
Block a user