diff --git a/assets/icons/cloudy_icon.svg b/assets/icons/cloudy_icon.svg new file mode 100644 index 0000000..6048264 --- /dev/null +++ b/assets/icons/cloudy_icon.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/assets/icons/comfortable_icon.svg b/assets/icons/comfortable_icon.svg new file mode 100644 index 0000000..57090a1 --- /dev/null +++ b/assets/icons/comfortable_icon.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/icons/dry_icon.svg b/assets/icons/dry_icon.svg new file mode 100644 index 0000000..9d0aad0 --- /dev/null +++ b/assets/icons/dry_icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/assets/icons/hazy_icon.svg b/assets/icons/hazy_icon.svg new file mode 100644 index 0000000..e7931fa --- /dev/null +++ b/assets/icons/hazy_icon.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/assets/icons/moist_icon.svg b/assets/icons/moist_icon.svg new file mode 100644 index 0000000..0b89800 --- /dev/null +++ b/assets/icons/moist_icon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/icons/rainy_icon.svg b/assets/icons/rainy_icon.svg new file mode 100644 index 0000000..e99fcec --- /dev/null +++ b/assets/icons/rainy_icon.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/icons/search_icon.svg b/assets/icons/search_icon.svg new file mode 100644 index 0000000..e5da4c9 --- /dev/null +++ b/assets/icons/search_icon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/icons/snowy_icon.svg b/assets/icons/snowy_icon.svg new file mode 100644 index 0000000..5b4a421 --- /dev/null +++ b/assets/icons/snowy_icon.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/icons/sunny_icon.svg b/assets/icons/sunny_icon.svg new file mode 100644 index 0000000..c0b7d72 --- /dev/null +++ b/assets/icons/sunny_icon.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/lib/features/scene/view/scene_auto_settings.dart b/lib/features/scene/view/scene_auto_settings.dart index af9db38..fba6204 100644 --- a/lib/features/scene/view/scene_auto_settings.dart +++ b/lib/features/scene/view/scene_auto_settings.dart @@ -3,10 +3,12 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_app/features/scene/bloc/create_scene/create_scene_bloc.dart'; import 'package:syncrow_app/features/scene/enum/create_scene_enum.dart'; import 'package:syncrow_app/features/scene/view/scene_tasks_view.dart'; +import 'package:syncrow_app/features/scene/view/settings/validity_page.dart'; import 'package:syncrow_app/features/scene/widgets/effective_period_setting/effective_period_bottom_sheet.dart'; import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart'; import 'package:syncrow_app/features/shared_widgets/default_container.dart'; import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart'; +import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart'; import 'package:syncrow_app/utils/context_extension.dart'; import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; @@ -37,6 +39,99 @@ class SceneAutoSettings extends StatelessWidget { height: MediaQuery.sizeOf(context).height, child: Column( children: [ + DefaultContainer( + child: Column( + children: [ + InkWell( + onTap: () { + Navigator.of(context).push(MaterialPageRoute( + builder: (context) =>const ValidityPage(), + )); + }, + child: Container( + padding: EdgeInsets.only(top: 12, bottom: 12), + child: const Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + BodyMedium( + text: 'Validity', + fontWeight: FontWeight.normal, + ), + Icon( + Icons.arrow_forward_ios, + size: 15, + color: ColorsManager.textGray, + ) + ], + ), + ), + ), + const Divider( + color: ColorsManager.backgroundColor, + ), + InkWell( + onTap: () { + context.customBottomSheet( + child: const EffectPeriodBottomSheetContent(), + ); + }, + child: Container( + padding: EdgeInsets.only(top: 12, bottom: 12), + child: const Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + BodyMedium( + text: 'Effective Period', + fontWeight: FontWeight.normal, + ), + Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Icon( + Icons.arrow_forward_ios, + size: 15, + color: ColorsManager.textGray, + ) + ], + ), + ], + ), + ), + ), + const Divider( + color: ColorsManager.backgroundColor, + ), + InkWell( + onTap: () {}, + child: Container( + padding: EdgeInsets.only(top: 12, bottom: 12), + child: const Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + BodyMedium( + text: 'Executed by', + fontWeight: FontWeight.normal, + ), + Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + BodyMedium( + fontColor: ColorsManager.textGray, + text: 'Cloud', + fontWeight: FontWeight.normal, + fontSize: 13, + ), + ], + ), + ], + ), + ), + ), + ], + ), + ), Padding( padding: const EdgeInsets.symmetric(vertical: 16), child: DefaultContainer( @@ -56,9 +151,7 @@ class SceneAutoSettings extends StatelessWidget { trailingWidget: const Icon(Icons.arrow_forward_ios_rounded), onPressed: () { - context.customBottomSheet( - child: const EffectPeriodBottomSheetContent(), - ); + }, ), ), diff --git a/lib/features/scene/view/settings/Temperature_dialog.dart b/lib/features/scene/view/settings/Temperature_dialog.dart new file mode 100644 index 0000000..e28d63c --- /dev/null +++ b/lib/features/scene/view/settings/Temperature_dialog.dart @@ -0,0 +1,165 @@ +import 'package:flutter/material.dart'; +import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; + +class TemperatureDialog extends StatefulWidget { + final Function(String label, int toggleIndex, String selectedCity)? + confirmTab; + + const TemperatureDialog({Key? key, this.confirmTab}) : super(key: key); + + @override + _TemperatureDialogState createState() => _TemperatureDialogState(); +} + +class _TemperatureDialogState extends State { + double _currentTemperature = 40; + String _selectedCity = 'Current City'; + int selectedToggleIndex = 1; + + @override + Widget build(BuildContext context) { + return Dialog( + backgroundColor: Colors.white, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20.0)), + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + const Text( + 'Temperature', + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.bold, + color: Colors.blue), + ), + const Divider(color: ColorsManager.greyColor), + ToggleButtons( + isSelected: [ + selectedToggleIndex == 0, + selectedToggleIndex == 1, + selectedToggleIndex == 2 + ], + onPressed: (index) { + setState(() { + selectedToggleIndex = index; + }); + }, + borderRadius: BorderRadius.circular(30), + selectedColor: Colors.white, + color: ColorsManager.blackColor, + fillColor: ColorsManager.primaryColorWithOpacity, + borderColor: ColorsManager.greyColor, + constraints: BoxConstraints.tight(const Size(70, 30)), + children: [ + _buildToggleOption('<', selectedToggleIndex == 0), + _buildToggleOption('=', selectedToggleIndex == 1), + _buildToggleOption('>', selectedToggleIndex == 2), + ], + ), + const SizedBox(height: 10), + Text( + '${_currentTemperature.toStringAsFixed(0)}°C', + style: TextStyle( + fontSize: 40, + fontWeight: FontWeight.bold, + color: ColorsManager.secondaryColor.withOpacity(0.5)), + ), + Slider( + activeColor: ColorsManager.secondaryColor.withOpacity(0.5), + inactiveColor: ColorsManager.grayBox, + thumbColor: ColorsManager.primaryColor, + value: _currentTemperature, + min: -40, + max: 40, + onChanged: (value) { + setState(() { + _currentTemperature = value; + }); + }, + ), + ElevatedButton( + onPressed: _selectCity, + child: Text( + _selectedCity, + style: const TextStyle( + color: ColorsManager.grayColor, + fontSize: 14, + fontWeight: FontWeight.w400), + ), + style: ElevatedButton.styleFrom( + backgroundColor: ColorsManager.grayBox.withOpacity(0.6), + ), + ), + const SizedBox(height: 20), + Row( + children: [ + _buildActionButton(context, 'Cancel', ColorsManager.textGray, + () => Navigator.of(context).pop()), + _buildActionButton( + context, + 'Confirm', + ColorsManager.primaryColor, + () { + widget.confirmTab!.call( + _currentTemperature.toStringAsFixed(0), + selectedToggleIndex, + _selectedCity); + }, + ), + ], + ) + ], + ), + ), + ); + } + + Widget _buildToggleOption(String label, bool isSelected) { + return SizedBox( + width: 70, + height: 30, + child: Container( + alignment: Alignment.center, + color: isSelected + ? ColorsManager.secondaryColor.withOpacity(0.2) + : ColorsManager.textGray, + child: Text(label), + ), + ); + } + + Widget _buildActionButton( + BuildContext context, String text, Color color, VoidCallback onTap) { + return Expanded( + child: InkWell( + onTap: onTap, + child: Container( + padding: const EdgeInsets.all(15), + decoration: BoxDecoration( + border: Border( + top: const BorderSide(color: ColorsManager.textGray), + left: text == 'Confirm' + ? const BorderSide(color: ColorsManager.textGray, width: 0.5) + : BorderSide.none, + ), + ), + child: Center( + child: Text( + text, + style: TextStyle( + color: color, fontSize: 14, fontWeight: FontWeight.w400), + ), + ), + ), + ), + ); + } + + void _selectCity() { + // Placeholder for the city selection function + setState(() { + _selectedCity = 'Selected City'; + }); + } +} diff --git a/lib/features/scene/view/settings/condition_dialog.dart b/lib/features/scene/view/settings/condition_dialog.dart new file mode 100644 index 0000000..0a7d3ef --- /dev/null +++ b/lib/features/scene/view/settings/condition_dialog.dart @@ -0,0 +1,38 @@ +import 'package:flutter/material.dart'; +import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart'; +import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; + +class ConditionDialog extends StatelessWidget { + const ConditionDialog({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return AlertDialog( + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20.0)), + contentPadding: EdgeInsets.zero, + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + _buildDialogOption(context, 'When all conditions are met'), + _buildDialogOption(context, 'When any condition is met'), + const Divider(color: ColorsManager.greyColor), + _buildDialogOption(context, 'Cancel', isCancel: true), + ], + ), + ); + } + + Widget _buildDialogOption(BuildContext context, String text, {bool isCancel = false}) { + return ListTile( + title: Center( + child: BodyMedium( + text: text, + fontSize: 15, + fontWeight: isCancel ? FontWeight.normal : FontWeight.w400, + fontColor: isCancel ? Colors.grey : null, + ), + ), + onTap: () => Navigator.of(context).pop(), + ); + } +} \ No newline at end of file diff --git a/lib/features/scene/view/settings/humidity_dialog.dart b/lib/features/scene/view/settings/humidity_dialog.dart new file mode 100644 index 0000000..8d78e73 --- /dev/null +++ b/lib/features/scene/view/settings/humidity_dialog.dart @@ -0,0 +1,221 @@ +import 'package:flutter/material.dart'; +import 'package:syncrow_app/features/devices/view/widgets/restart_status_dialog.dart'; +import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart'; +import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart'; +import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; +import 'package:syncrow_app/generated/assets.dart'; +import 'package:flutter_svg/flutter_svg.dart'; + +class HumidityDialog extends StatefulWidget { + final String label1; + final String label2; + final String label3; + final String title; + final Function()? cancelTab; + final Function(String labelSelected)? confirmTab; + + final String? initialSelectedLabel; + + HumidityDialog({ + required this.label1, + required this.label2, + required this.label3, + required this.title, + required this.cancelTab, + required this.confirmTab, + this.initialSelectedLabel, + }); + + @override + _HumidityDialogState createState() => _HumidityDialogState(); +} + +class _HumidityDialogState extends State { + late String _selectedOption; + String _selectedCity = 'Current City'; + + @override + void initState() { + super.initState(); + + _selectedOption = widget.initialSelectedLabel ?? ''; + } + + @override + Widget build(BuildContext context) { + return AlertDialog( + contentPadding: EdgeInsets.zero, + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + const SizedBox( + height: 10, + ), + BodyLarge( + text: widget.title, + fontWeight: FontWeight.w700, + fontColor: ColorsManager.primaryColor, + fontSize: 16, + ), + const Padding( + padding: EdgeInsets.only(left: 15, right: 15), + child: Divider( + color: ColorsManager.textGray, + ), + ), + Padding( + padding: const EdgeInsets.only(left: 15, right: 15), + child: Column( + children: [ + _buildCheckboxOption( + icon: Assets.dryIcon, + label: widget.label1, + onTap: (v) { + _selectedOption = v; + }, + ), + _buildCheckboxOption( + icon: Assets.comfortableIcon, + label: widget.label2, + onTap: (v) { + _selectedOption = v; + }, + ), + _buildCheckboxOption( + icon: Assets.moistIcon, + label: widget.label3, + onTap: (v) { + _selectedOption = v; + }, + ), + Container( + height: 35, + child: ElevatedButton( + onPressed: () {}, + child: Text( + _selectedCity, + style: TextStyle( + color: ColorsManager.grayColor, + fontSize: 14, + fontWeight: FontWeight.w400), + ), + style: ElevatedButton.styleFrom( + backgroundColor: ColorsManager.grayBox.withOpacity(0.6), + ), + ), + ), + const SizedBox( + height: 10, + ) + ], + ), + ), + Row( + children: [ + Expanded( + child: Container( + decoration: const BoxDecoration( + border: Border( + right: BorderSide( + color: ColorsManager.textGray, + width: 0.5, + ), + top: BorderSide( + color: ColorsManager.textGray, + width: 1.0, + ), + )), + child: SizedBox( + child: InkWell( + onTap: widget.cancelTab, + child: const Padding( + padding: EdgeInsets.all(15), + child: Center( + child: Text( + 'Cancel', + style: TextStyle( + color: ColorsManager.textGray, + fontSize: 14, + fontWeight: FontWeight.w400), + ), + ), + ), + ), + ), + ), + ), + Expanded( + child: Container( + decoration: const BoxDecoration( + border: Border( + left: BorderSide( + color: ColorsManager.textGray, + width: 0.5, + ), + top: BorderSide( + color: ColorsManager.textGray, + width: 1.0, + ), + )), + child: InkWell( + onTap: () { + widget.confirmTab!.call(_selectedCity); + }, + child: const Padding( + padding: EdgeInsets.all(15), + child: Center( + child: Text( + 'Confirm', + style: TextStyle( + color: ColorsManager.primaryColor, + fontSize: 14, + fontWeight: FontWeight.w400), + ), + ), + )), + )) + ], + ) + ], + ), + ); + } + + Widget _buildCheckboxOption( + {required String label, required String icon, Function(String)? onTap}) { + return Padding( + padding: const EdgeInsets.only(bottom: 10, top: 10), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + SvgPicture.asset(icon), + SizedBox( + width: 15, + ), + BodyMedium( + text: label, + style: + const TextStyle(fontSize: 15, fontWeight: FontWeight.w400), + ), + ], + ), + CircularCheckbox( + value: _selectedOption == label, + onChanged: (bool? value) { + if (value == true) { + setState(() { + _selectedOption = label; + }); + if (onTap != null) { + onTap(label); + } + } + }, + ), + ], + ), + ); + } +} diff --git a/lib/features/scene/view/settings/validity_page.dart b/lib/features/scene/view/settings/validity_page.dart new file mode 100644 index 0000000..b8a444b --- /dev/null +++ b/lib/features/scene/view/settings/validity_page.dart @@ -0,0 +1,120 @@ +import 'package:flutter/material.dart'; +import 'package:syncrow_app/features/scene/view/settings/Temperature_dialog.dart'; +import 'package:syncrow_app/features/scene/view/settings/condition_dialog.dart'; +import 'package:syncrow_app/features/scene/view/settings/humidity_dialog.dart'; +import 'package:syncrow_app/features/scene/view/settings/weather_bottom_sheet.dart'; +import 'package:syncrow_app/features/scene/view/settings/weather_dialog.dart'; +import 'package:syncrow_app/features/scene/view/settings/wind_speed_dialog.dart'; +import 'package:syncrow_app/features/shared_widgets/default_container.dart'; +import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart'; +import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart'; +import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart'; +import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; + +class ValidityPage extends StatelessWidget { + const ValidityPage({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return DefaultScaffold( + title: 'Validity', + padding: EdgeInsets.zero, + leading: IconButton( + onPressed: () => Navigator.of(context).pop(), + icon: const Icon(Icons.arrow_back_ios), + ), + child: Column( + children: [ + DefaultContainer( + child: ListTile( + title: const BodyMedium( + text: 'When any condition is met', + fontWeight: FontWeight.normal, + ), + trailing: const Icon(Icons.arrow_forward_ios, + size: 15, color: ColorsManager.textGray), + onTap: () => _showConditionDialog(context), + ), + ), + const SizedBox(height: 16), + InkWell( + onTap: () => showModalBottomSheet( + context: context, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical(top: Radius.circular(20.0)), + ), + builder: (BuildContext context) => WeatherBottomSheet( + showTemperatureDialog: () { + showDialog( + context: context, + builder: (BuildContext context) => TemperatureDialog( + confirmTab: (label, toggleIndex, selectedCity) { + print(label); + print(toggleIndex); + print(selectedCity); + }, + ), + ); + }, + showHumidityDialog: () { + showDialog( + context: context, + builder: (BuildContext context) => HumidityDialog( + initialSelectedLabel: 'Dry', + cancelTab: () => Navigator.of(context).pop(), + confirmTab: (v) {}, + title: 'Humidity', + label1: 'Dry', + label2: 'Comfortable', + label3: 'Moist', + ), + ); + }, + showWeatherDialog: () { + showDialog( + context: context, + builder: (BuildContext context) => WeatherDialog( + initialSelectedLabel: 'Sunny', + cancelTab: () {}, + confirmTab: (selectedOption) {}, + title: 'Weather', + label1: 'Sunny', + label2: 'Cloudy', + label3: 'Rainy', + label4: 'Snowy', + label5: 'Hazy', + ), + ); + }, + showWindSpeedDialog: () { + showDialog( + context: context, + builder: (BuildContext context) => WindSpeedDialog( + confirmTab: (selectedTemperature, selectedToggleIndex, + selectedCity) {}, + ), + ); + }, + ), + ), + child: const DefaultContainer( + child: Center( + child: Padding( + padding: EdgeInsets.all(5.0), + child: BodyLarge(text: '+ Add'), + ), + ), + ), + ), + ], + ), + ); + } + + void _showConditionDialog(BuildContext context) { + showDialog( + context: context, + builder: (BuildContext context) => const ConditionDialog(), + ); + } +} diff --git a/lib/features/scene/view/settings/weather_bottom_sheet.dart b/lib/features/scene/view/settings/weather_bottom_sheet.dart new file mode 100644 index 0000000..cf19f96 --- /dev/null +++ b/lib/features/scene/view/settings/weather_bottom_sheet.dart @@ -0,0 +1,54 @@ +import 'package:flutter/material.dart'; +import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart'; +import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; + +class WeatherBottomSheet extends StatelessWidget { + final VoidCallback showTemperatureDialog; + final VoidCallback showHumidityDialog; + final VoidCallback showWeatherDialog; + final VoidCallback showWindSpeedDialog; + + const WeatherBottomSheet({ + Key? key, + required this.showTemperatureDialog, + required this.showHumidityDialog, + required this.showWeatherDialog, + required this.showWindSpeedDialog, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + const Center( + child: Text( + "When Weather Changes", + style: TextStyle( + fontSize: 16.0, + fontWeight: FontWeight.w700, + color: Colors.blue), + ), + ), + const Divider(color: ColorsManager.greyColor), + _buildWeatherOption(context, 'Temperature', showTemperatureDialog), + _buildWeatherOption(context, 'Humidity', showHumidityDialog), + _buildWeatherOption(context, 'Weather', showWeatherDialog), + _buildWeatherOption( + context, 'Wind Speed', showWindSpeedDialog), + ], + ), + ); + } + + Widget _buildWeatherOption( + BuildContext context, String title, VoidCallback onTap) { + return ListTile( + title: BodyMedium(text: title, fontSize: 15, fontWeight: FontWeight.w400), + trailing: const Icon(Icons.chevron_right, color: ColorsManager.textGray), + onTap: onTap, + ); + } +} diff --git a/lib/features/scene/view/settings/weather_dialog.dart b/lib/features/scene/view/settings/weather_dialog.dart new file mode 100644 index 0000000..abd0e1b --- /dev/null +++ b/lib/features/scene/view/settings/weather_dialog.dart @@ -0,0 +1,241 @@ +import 'package:flutter/material.dart'; +import 'package:syncrow_app/features/devices/view/widgets/restart_status_dialog.dart'; +import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart'; +import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart'; +import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; +import 'package:syncrow_app/generated/assets.dart'; +import 'package:flutter_svg/flutter_svg.dart'; + +class WeatherDialog extends StatefulWidget { + final String label1; + final String label2; + final String label3; + final String label4; + final String label5; + + final String title; + final Function()? cancelTab; + final Function(String label)? confirmTab; + + final String? initialSelectedLabel; + + WeatherDialog({ + required this.label1, + required this.label2, + required this.label3, + required this.label4, + required this.label5, + required this.title, + required this.cancelTab, + required this.confirmTab, + this.initialSelectedLabel, + }); + + @override + _WeatherDialogState createState() => _WeatherDialogState(); +} + +class _WeatherDialogState extends State { + late String _selectedOption; + String _selectedCity = 'Current City'; + + @override + void initState() { + super.initState(); + + _selectedOption = widget.initialSelectedLabel ?? ''; + } + + @override + Widget build(BuildContext context) { + return AlertDialog( + backgroundColor: Colors.white, + contentPadding: EdgeInsets.zero, + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + const SizedBox( + height: 10, + ), + BodyLarge( + text: widget.title, + fontWeight: FontWeight.w700, + fontColor: ColorsManager.primaryColor, + fontSize: 16, + ), + const Padding( + padding: EdgeInsets.only(left: 15, right: 15), + child: Divider( + color: ColorsManager.textGray, + ), + ), + Padding( + padding: const EdgeInsets.only(left: 15, right: 15), + child: Column( + children: [ + _buildCheckboxOption( + icon: Assets.sunnyIcon, + label: widget.label1, + onTap: (v) { + _selectedOption = v; + }, + ), + _buildCheckboxOption( + icon: Assets.cloudyIcon, + label: widget.label2, + onTap: (v) { + _selectedOption = v; + }, + ), + _buildCheckboxOption( + icon: Assets.rainyIcon, + label: widget.label3, + onTap: (v) { + _selectedOption = v; + }, + ), + _buildCheckboxOption( + icon: Assets.snowyIcon, + label: widget.label4, + onTap: (v) { + _selectedOption = v; + }, + ), + _buildCheckboxOption( + icon: Assets.hazyIcon, + label: widget.label5, + onTap: (v) { + _selectedOption = v; + }, + ), + Container( + height: 35, + child: ElevatedButton( + onPressed: () {}, + child: Text( + _selectedCity, + style: TextStyle( + color: ColorsManager.grayColor, + fontSize: 14, + fontWeight: FontWeight.w400), + ), + style: ElevatedButton.styleFrom( + backgroundColor: ColorsManager.grayBox.withOpacity(0.6), + ), + ), + ), + const SizedBox( + height: 10, + ) + ], + ), + ), + Row( + children: [ + Expanded( + child: Container( + decoration: const BoxDecoration( + border: Border( + right: BorderSide( + color: ColorsManager.textGray, + width: 0.5, + ), + top: BorderSide( + color: ColorsManager.textGray, + width: 1.0, + ), + )), + child: SizedBox( + child: InkWell( + onTap: widget.cancelTab, + child: const Padding( + padding: EdgeInsets.all(15), + child: Center( + child: Text( + 'Cancel', + style: TextStyle( + color: ColorsManager.textGray, + fontSize: 14, + fontWeight: FontWeight.w400), + ), + ), + ), + ), + ), + ), + ), + Expanded( + child: Container( + decoration: const BoxDecoration( + border: Border( + left: BorderSide( + color: ColorsManager.textGray, + width: 0.5, + ), + top: BorderSide( + color: ColorsManager.textGray, + width: 1.0, + ), + )), + child: InkWell( + onTap: () { + widget.confirmTab!.call(_selectedOption); + }, + child: const Padding( + padding: EdgeInsets.all(15), + child: Center( + child: Text( + 'Confirm', + style: TextStyle( + color: ColorsManager.primaryColor, + fontSize: 14, + fontWeight: FontWeight.w400), + ), + ), + )), + )) + ], + ) + ], + ), + ); + } + + Widget _buildCheckboxOption( + {required String label, required String icon, Function(String)? onTap}) { + return Padding( + padding: const EdgeInsets.only(bottom: 10, top: 10), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + SvgPicture.asset(icon), + SizedBox( + width: 15, + ), + BodyMedium( + text: label, + style: + const TextStyle(fontSize: 15, fontWeight: FontWeight.w400), + ), + ], + ), + CircularCheckbox( + value: _selectedOption == label, + onChanged: (bool? value) { + if (value == true) { + setState(() { + _selectedOption = label; + }); + if (onTap != null) { + onTap(label); + } + } + }, + ), + ], + ), + ); + } +} diff --git a/lib/features/scene/view/settings/wind_speed_dialog.dart b/lib/features/scene/view/settings/wind_speed_dialog.dart new file mode 100644 index 0000000..a6fe128 --- /dev/null +++ b/lib/features/scene/view/settings/wind_speed_dialog.dart @@ -0,0 +1,160 @@ +import 'package:flutter/material.dart'; +import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; + +class WindSpeedDialog extends StatefulWidget { + final Function(double selectedTemperature, int selectedToggleIndex, + String selectedCity)? confirmTab; + + const WindSpeedDialog({ + Key? key, + this.confirmTab, + }) : super(key: key); + + @override + _WindSpeedDialogState createState() => _WindSpeedDialogState(); +} + +class _WindSpeedDialogState extends State { + double _currentSpeed = 40; + String _selectedCity = 'Current City'; + int selectedToggleIndex = 1; + + @override + Widget build(BuildContext context) { + return Dialog( + backgroundColor: Colors.white, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20.0)), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + const SizedBox(height: 10), + Text( + 'Wind Speed', + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.w700, + color: ColorsManager.primaryColor.withOpacity(0.5)), + ), + const Divider(color: ColorsManager.greyColor), + ToggleButtons( + isSelected: [ + selectedToggleIndex == 0, + selectedToggleIndex == 1, + selectedToggleIndex == 2 + ], + onPressed: (index) { + setState(() { + selectedToggleIndex = index; + }); + }, + borderRadius: BorderRadius.circular(30), + selectedColor: Colors.white, + color: ColorsManager.blackColor, + fillColor: ColorsManager.primaryColorWithOpacity, + borderColor: ColorsManager.greyColor, + constraints: BoxConstraints.tight(const Size(70, 30)), + children: [ + _buildToggleOption('<', selectedToggleIndex == 0), + _buildToggleOption('=', selectedToggleIndex == 1), + _buildToggleOption('>', selectedToggleIndex == 2), + ], + ), + const SizedBox(height: 10), + Text( + '${_currentSpeed.toStringAsFixed(0)} m/s', + style: TextStyle( + fontSize: 40, + fontWeight: FontWeight.bold, + color: ColorsManager.secondaryColor.withOpacity(0.5)), + ), + Slider( + activeColor: ColorsManager.secondaryColor.withOpacity(0.5), + inactiveColor: ColorsManager.grayBox, + thumbColor: ColorsManager.primaryColor, + value: _currentSpeed, + min: 0, + max: 62, + onChanged: (value) { + setState(() { + _currentSpeed = value; + }); + }, + ), + ElevatedButton( + onPressed: _selectCity, + child: Text( + _selectedCity, + style: const TextStyle( + color: ColorsManager.grayColor, + fontSize: 14, + fontWeight: FontWeight.w400), + ), + style: ElevatedButton.styleFrom( + backgroundColor: ColorsManager.grayBox.withOpacity(0.6), + ), + ), + const SizedBox(height: 20), + Row( + children: [ + _buildActionButton(context, 'Cancel', ColorsManager.textGray, + () => Navigator.of(context).pop()), + _buildActionButton(context, 'Confirm', ColorsManager.primaryColor, + () { + widget.confirmTab! + .call(_currentSpeed, selectedToggleIndex, _selectedCity); + }), + ], + ) + ], + ), + ); + } + + Widget _buildToggleOption(String label, bool isSelected) { + return SizedBox( + width: 70, + height: 30, + child: Container( + alignment: Alignment.center, + color: isSelected + ? ColorsManager.secondaryColor.withOpacity(0.2) + : ColorsManager.textGray, + child: Text(label), + ), + ); + } + + Widget _buildActionButton( + BuildContext context, String text, Color color, VoidCallback onTap) { + return Expanded( + child: InkWell( + onTap: onTap, + child: Container( + padding: const EdgeInsets.all(15), + decoration: BoxDecoration( + border: Border( + top: const BorderSide(color: ColorsManager.textGray), + left: text == 'Confirm' + ? const BorderSide(color: ColorsManager.textGray, width: 0.5) + : BorderSide.none, + ), + ), + child: Center( + child: Text( + text, + style: TextStyle( + color: color, fontSize: 14, fontWeight: FontWeight.w400), + ), + ), + ), + ), + ); + } + + void _selectCity() { + // Placeholder for the city selection function + setState(() { + _selectedCity = 'Selected City'; + }); + } +} diff --git a/lib/generated/assets.dart b/lib/generated/assets.dart index acf46f7..e23a191 100644 --- a/lib/generated/assets.dart +++ b/lib/generated/assets.dart @@ -1081,5 +1081,23 @@ class Assets { static const String gang1touch = "assets/icons/1gang_touch.svg"; static const String gang2touch = "assets/icons/2gang_touch.svg"; static const String gang3touch = "assets/icons/3gang_touch.svg"; + + static const String frequencyIcon = "assets/icons/frequency_icon.svg"; + static const String voltMeterIcon = "assets/icons/volt_meter_icon.svg"; + static const String powerActiveIcon = "assets/icons/power_active_icon.svg"; + static const String searchIcon = "assets/icons/search_icon.svg"; + + + static const String comfortableIcon = "assets/icons/comfortable_icon.svg"; + static const String moistIcon = "assets/icons/moist_icon.svg"; + static const String dryIcon = "assets/icons/dry_icon.svg"; + + + + static const String hazyIcon = "assets/icons/hazy_icon.svg"; + static const String snowyIcon = "assets/icons/snowy_icon.svg"; + static const String rainyIcon = "assets/icons/rainy_icon.svg"; + static const String cloudyIcon = "assets/icons/cloudy_icon.svg"; + static const String sunnyIcon = "assets/icons/sunny_icon.svg"; //leakNormalIcon }