diff --git a/assets/icons/functions_icons/ac_cooling.svg b/assets/icons/functions_icons/ac_cooling.svg new file mode 100644 index 0000000..e95c0d4 --- /dev/null +++ b/assets/icons/functions_icons/ac_cooling.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/assets/icons/functions_icons/ac_fan_auto.svg b/assets/icons/functions_icons/ac_fan_auto.svg new file mode 100644 index 0000000..0acacfe --- /dev/null +++ b/assets/icons/functions_icons/ac_fan_auto.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/assets/icons/functions_icons/ac_fan_high.svg b/assets/icons/functions_icons/ac_fan_high.svg new file mode 100644 index 0000000..d613153 --- /dev/null +++ b/assets/icons/functions_icons/ac_fan_high.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/assets/icons/functions_icons/ac_fan_low.svg b/assets/icons/functions_icons/ac_fan_low.svg new file mode 100644 index 0000000..f4bf56b --- /dev/null +++ b/assets/icons/functions_icons/ac_fan_low.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/assets/icons/functions_icons/ac_fan_middle.svg b/assets/icons/functions_icons/ac_fan_middle.svg new file mode 100644 index 0000000..ee94023 --- /dev/null +++ b/assets/icons/functions_icons/ac_fan_middle.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/assets/icons/functions_icons/ac_heating.svg b/assets/icons/functions_icons/ac_heating.svg new file mode 100644 index 0000000..47a160c --- /dev/null +++ b/assets/icons/functions_icons/ac_heating.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/assets/icons/functions_icons/ac_power.svg b/assets/icons/functions_icons/ac_power.svg new file mode 100644 index 0000000..cc2127f --- /dev/null +++ b/assets/icons/functions_icons/ac_power.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/icons/functions_icons/ac_power_off.svg b/assets/icons/functions_icons/ac_power_off.svg new file mode 100644 index 0000000..70f7f9a --- /dev/null +++ b/assets/icons/functions_icons/ac_power_off.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/icons/functions_icons/celsius_degrees.svg b/assets/icons/functions_icons/celsius_degrees.svg new file mode 100644 index 0000000..7acbd6e --- /dev/null +++ b/assets/icons/functions_icons/celsius_degrees.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/assets/icons/functions_icons/child_lock.svg b/assets/icons/functions_icons/child_lock.svg new file mode 100644 index 0000000..6b0138b --- /dev/null +++ b/assets/icons/functions_icons/child_lock.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/icons/functions_icons/fan_speed.svg b/assets/icons/functions_icons/fan_speed.svg new file mode 100644 index 0000000..07a4883 --- /dev/null +++ b/assets/icons/functions_icons/fan_speed.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/assets/icons/functions_icons/freezing.svg b/assets/icons/functions_icons/freezing.svg new file mode 100644 index 0000000..6c02f2e --- /dev/null +++ b/assets/icons/functions_icons/freezing.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/icons/functions_icons/light_countdown.svg b/assets/icons/functions_icons/light_countdown.svg new file mode 100644 index 0000000..94f65b9 --- /dev/null +++ b/assets/icons/functions_icons/light_countdown.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/icons/functions_icons/scene_child_lock.svg b/assets/icons/functions_icons/scene_child_lock.svg new file mode 100644 index 0000000..7e56164 --- /dev/null +++ b/assets/icons/functions_icons/scene_child_lock.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/assets/icons/functions_icons/scene_child_unlock.svg b/assets/icons/functions_icons/scene_child_unlock.svg new file mode 100644 index 0000000..4eafbde --- /dev/null +++ b/assets/icons/functions_icons/scene_child_unlock.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/assets/icons/functions_icons/scene_refresh.svg b/assets/icons/functions_icons/scene_refresh.svg new file mode 100644 index 0000000..c54ffb0 --- /dev/null +++ b/assets/icons/functions_icons/scene_refresh.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/icons/functions_icons/sesitivity_operation_icon.svg b/assets/icons/functions_icons/sesitivity_operation_icon.svg new file mode 100644 index 0000000..612148c --- /dev/null +++ b/assets/icons/functions_icons/sesitivity_operation_icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/icons/functions_icons/tempreture.svg b/assets/icons/functions_icons/tempreture.svg new file mode 100644 index 0000000..448083a --- /dev/null +++ b/assets/icons/functions_icons/tempreture.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/lib/features/scene/enum/ac_values.dart b/lib/features/scene/enum/ac_values.dart new file mode 100644 index 0000000..5694fdd --- /dev/null +++ b/lib/features/scene/enum/ac_values.dart @@ -0,0 +1,7 @@ +// ignore_for_file: constant_identifier_names + +enum AcValuesEnums { + Cooling, + Heating, + Ventilation, +} diff --git a/lib/features/scene/helper/scene_helper.dart b/lib/features/scene/helper/scene_helper.dart index 2c93067..eadef9a 100644 --- a/lib/features/scene/helper/scene_helper.dart +++ b/lib/features/scene/helper/scene_helper.dart @@ -1,50 +1,249 @@ import 'package:syncrow_app/features/devices/model/function_model.dart'; +import 'package:syncrow_app/features/scene/enum/ac_values.dart'; +import 'package:syncrow_app/features/scene/model/scene_static_function.dart'; +import 'package:syncrow_app/generated/assets.dart'; import 'package:syncrow_app/utils/resource_manager/constants.dart'; mixin SceneHelper { - get lightBulbFunctions => null; - - get wallSensorFunctions => null; - - get acFunctions => null; - - get doorLockFunctions => null; - - get curtainFunctions => null; - - get threeGangFunctions => null; - - get gatewayFunctions => null; - - getFunctionsWithIcons( + List getFunctionsWithIcons( {DeviceType? type, required List functions}) { switch (type) { case DeviceType.LightBulb: - return lightBulbFunctions; + return lightBulbFunctions(functions); case DeviceType.CeilingSensor: return ceilingSensorFunctions(functions); case DeviceType.WallSensor: - return wallSensorFunctions; + return wallSensorFunctions(functions); case DeviceType.AC: - return acFunctions; + return acFunctions(functions); case DeviceType.DoorLock: - return doorLockFunctions; + return doorLockFunctions(functions); case DeviceType.Curtain: - return curtainFunctions; + return curtainFunctions(functions); case DeviceType.ThreeGang: - return threeGangFunctions; + return threeGangFunctions(functions); case DeviceType.Gateway: - return gatewayFunctions; + return gatewayFunctions(functions); default: - return lightBulbFunctions; + return lightBulbFunctions(functions); } } - - ceilingSensorFunctions(List functions) { - List temp = []; - for (var item in functions) { - + + String getTitle({DeviceType? type}) { + switch (type) { + case DeviceType.LightBulb: + return 'Light Bulb Functions'; + case DeviceType.CeilingSensor: + return 'Presence Sensor Functions'; + case DeviceType.WallSensor: + return 'Human Presence Sensor Functions'; + case DeviceType.AC: + return 'AC Functions'; + case DeviceType.DoorLock: + return 'Door Lock Functions'; + case DeviceType.Curtain: + return 'Curtain Functions'; + case DeviceType.ThreeGang: + return '3G Light Switch Functions'; + case DeviceType.Gateway: + return 'Gateway Functions'; + default: + return ''; } - return temp; + } + + /// presence sensor + List ceilingSensorFunctions( + List functions) { + return [ + SceneStaticFunction( + icon: Assets.assetsSensitivityFunction, + name: 'Sensitivity', + code: 'sensitivity', + operationalValues: [ + StaticFunctionOperationHelper( + icon: Assets.assetsSensitivityOperationIcon, value: "1"), + StaticFunctionOperationHelper( + icon: Assets.assetsSensitivityOperationIcon, value: "2"), + StaticFunctionOperationHelper( + icon: Assets.assetsSensitivityOperationIcon, value: "3"), + StaticFunctionOperationHelper( + icon: Assets.assetsSensitivityOperationIcon, value: "4"), + StaticFunctionOperationHelper( + icon: Assets.assetsSensitivityOperationIcon, value: "5"), + StaticFunctionOperationHelper( + icon: Assets.assetsSensitivityOperationIcon, value: "6"), + StaticFunctionOperationHelper( + icon: Assets.assetsSensitivityOperationIcon, value: "7"), + StaticFunctionOperationHelper( + icon: Assets.assetsSensitivityOperationIcon, value: "8"), + StaticFunctionOperationHelper( + icon: Assets.assetsSensitivityOperationIcon, value: "9"), + StaticFunctionOperationHelper( + icon: Assets.assetsSensitivityOperationIcon, value: "10"), + ], + ), + ]; } } + +List curtainFunctions(List functions) { + return []; +} + +List doorLockFunctions(List functions) { + return []; +} + +List wallSensorFunctions(List functions) { + return []; +} + +List lightBulbFunctions(List functions) { + return []; +} + +List gatewayFunctions(List functions) { + return []; +} + +List threeGangFunctions(List functions) { + return [ + SceneStaticFunction( + icon: Assets.assetsAcPower, + name: 'Light 1 Switch', + code: 'switch_1', + operationalValues: [ + StaticFunctionOperationHelper(icon: Assets.assetsAcPower, value: "ON"), + StaticFunctionOperationHelper( + icon: Assets.assetsAcPowerOFF, value: "OFF"), + StaticFunctionOperationHelper( + icon: Assets.assetsSceneRefresh, value: "Reverse Switch"), + ], + ), + SceneStaticFunction( + icon: Assets.assetsAcPower, + name: 'Light 2 Switch', + code: 'switch_2', + operationalValues: [ + StaticFunctionOperationHelper(icon: Assets.assetsAcPower, value: "ON"), + StaticFunctionOperationHelper( + icon: Assets.assetsAcPowerOFF, value: "OFF"), + StaticFunctionOperationHelper( + icon: Assets.assetsSceneRefresh, value: "Reverse Switch"), + ], + ), + SceneStaticFunction( + icon: Assets.assetsAcPower, + name: 'Light 3 Switch', + code: 'switch_3', + operationalValues: [ + StaticFunctionOperationHelper(icon: Assets.assetsAcPower, value: "ON"), + StaticFunctionOperationHelper( + icon: Assets.assetsAcPowerOFF, value: "OFF"), + StaticFunctionOperationHelper( + icon: Assets.assetsSceneRefresh, value: "Reverse Switch"), + ], + ), + SceneStaticFunction( + icon: Assets.assetsLightCountdown, + name: 'Light 1 CountDown', + code: 'countdown_1', + operationalValues: [], + ), + SceneStaticFunction( + icon: Assets.assetsLightCountdown, + name: 'Light 2 CountDown', + code: 'countdown_1', + operationalValues: [], + ), + SceneStaticFunction( + icon: Assets.assetsLightCountdown, + name: 'Light 3 CountDown', + code: 'countdown_1', + operationalValues: [], + ), + ]; +} + +/// smart ac thermostat +List acFunctions(List functions) { + return [ + SceneStaticFunction( + icon: Assets.assetsAcPower, + name: 'Power', + code: 'switch', + operationalValues: [ + StaticFunctionOperationHelper(icon: Assets.assetsAcPower, value: "ON"), + StaticFunctionOperationHelper( + icon: Assets.assetsAcPowerOFF, value: "OFF"), + ], + ), + SceneStaticFunction( + icon: Assets.assetsFreezing, + name: 'Mode', + code: 'mode', + operationalValues: [ + StaticFunctionOperationHelper( + icon: Assets.assetsAcCooling, + value: AcValuesEnums.Cooling.name, + ), + StaticFunctionOperationHelper( + icon: Assets.assetsAcHeating, + value: AcValuesEnums.Heating.name, + ), + StaticFunctionOperationHelper( + icon: Assets.assetsFanSpeed, + value: AcValuesEnums.Ventilation.name, + ), + ], + ), + SceneStaticFunction( + icon: Assets.assetsTempreture, + name: 'Set Temperature', + code: 'temp_set', + operationalValues: [ + StaticFunctionOperationHelper( + icon: Assets.assetsCelsiusDegrees, value: "COOL TO"), + ], + ), + SceneStaticFunction( + icon: Assets.assetsFanSpeed, + name: 'Fan Speed', + code: 'level', + operationalValues: [ + StaticFunctionOperationHelper( + icon: Assets.assetsAcFanLow, + value: ValueACRange.LOW.name, + ), + StaticFunctionOperationHelper( + icon: Assets.assetsAcFanMiddle, + value: ValueACRange.MIDDLE.name, + ), + StaticFunctionOperationHelper( + icon: Assets.assetsAcFanHigh, + value: ValueACRange.HIGH.name, + ), + StaticFunctionOperationHelper( + icon: Assets.assetsAcFanAuto, + value: ValueACRange.AUTO.name, + ), + ], + ), + SceneStaticFunction( + icon: Assets.assetsChildLock, + name: 'Child Lock', + code: 'child_lock', + operationalValues: [ + StaticFunctionOperationHelper( + icon: Assets.assetsSceneChildLock, + value: 'Lock', + ), + StaticFunctionOperationHelper( + icon: Assets.assetsSceneChildUnlock, + value: 'Unlock', + ), + ], + ), + ]; +} diff --git a/lib/features/scene/model/scene_static_function.dart b/lib/features/scene/model/scene_static_function.dart new file mode 100644 index 0000000..b073516 --- /dev/null +++ b/lib/features/scene/model/scene_static_function.dart @@ -0,0 +1,135 @@ +import 'dart:convert'; + +import 'package:flutter/foundation.dart'; + +class SceneStaticFunction { + final String icon; + final String name; + final String code; + final List operationalValues; + + SceneStaticFunction({ + required this.icon, + required this.name, + required this.code, + required this.operationalValues, + }); + + SceneStaticFunction copyWith({ + String? icon, + String? name, + String? code, + List? operationalValues, + }) { + return SceneStaticFunction( + icon: icon ?? this.icon, + name: name ?? this.name, + code: code ?? this.code, + operationalValues: operationalValues ?? this.operationalValues, + ); + } + + Map toMap() { + return { + 'icon': icon, + 'name': name, + 'code': code, + 'operationalValues': operationalValues.map((x) => x.toMap()).toList(), + }; + } + + factory SceneStaticFunction.fromMap(Map map) { + return SceneStaticFunction( + icon: map['icon'] ?? '', + name: map['name'] ?? '', + code: map['code'] ?? '', + operationalValues: List.from( + map['operationalValues'] + ?.map((x) => StaticFunctionOperationHelper.fromMap(x))), + ); + } + + String toJson() => json.encode(toMap()); + + factory SceneStaticFunction.fromJson(String source) => + SceneStaticFunction.fromMap(json.decode(source)); + + @override + String toString() { + return 'SceneStaticFunction(icon: $icon, name: $name, code: $code, operationalValues: $operationalValues)'; + } + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + + return other is SceneStaticFunction && + other.icon == icon && + other.name == name && + other.code == code && + listEquals(other.operationalValues, operationalValues); + } + + @override + int get hashCode { + return icon.hashCode ^ + name.hashCode ^ + code.hashCode ^ + operationalValues.hashCode; + } +} + +class StaticFunctionOperationHelper { + final String icon; + final String value; + + StaticFunctionOperationHelper({ + required this.icon, + required this.value, + }); + + StaticFunctionOperationHelper copyWith({ + String? icon, + String? value, + }) { + return StaticFunctionOperationHelper( + icon: icon ?? this.icon, + value: value ?? this.value, + ); + } + + Map toMap() { + return { + 'icon': icon, + 'value': value, + }; + } + + factory StaticFunctionOperationHelper.fromMap(Map map) { + return StaticFunctionOperationHelper( + icon: map['icon'] ?? '', + value: map['value'] ?? '', + ); + } + + String toJson() => json.encode(toMap()); + + factory StaticFunctionOperationHelper.fromJson(String source) => + StaticFunctionOperationHelper.fromMap(json.decode(source)); + + @override + String toString() => + 'StaticFunctionOperationHelper(icon: $icon, value: $value)'; + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + + return other is StaticFunctionOperationHelper && + other.icon == icon && + other.value == value; + } + + @override + int get hashCode => icon.hashCode ^ value.hashCode; +} diff --git a/lib/features/scene/view/create_scene_view.dart b/lib/features/scene/view/create_scene_view.dart index 097011e..afc8de5 100644 --- a/lib/features/scene/view/create_scene_view.dart +++ b/lib/features/scene/view/create_scene_view.dart @@ -25,7 +25,7 @@ class CreateSceneView extends StatelessWidget { child: const SceneListTile( assetPath: Assets.handClickIcon, titleString: StringsManager.tapToRun, - subtitle: StringsManager.turnOffAllLights, + subtitleString: StringsManager.turnOffAllLights, ), onTap: () => Navigator.pushNamed( context, @@ -39,7 +39,7 @@ class CreateSceneView extends StatelessWidget { child: const SceneListTile( assetPath: Assets.refreshIcon, titleString: StringsManager.whenDeviceStatusChanges, - subtitle: StringsManager.whenUnusualActivityIsDetected, + subtitleString: StringsManager.whenUnusualActivityIsDetected, ), onTap: () {}, ), diff --git a/lib/features/scene/view/device_functions_view.dart b/lib/features/scene/view/device_functions_view.dart index 6e7ebb8..2a955a5 100644 --- a/lib/features/scene/view/device_functions_view.dart +++ b/lib/features/scene/view/device_functions_view.dart @@ -1,82 +1,124 @@ import 'package:flutter/material.dart'; import 'package:syncrow_app/features/devices/model/device_model.dart'; import 'package:syncrow_app/features/scene/helper/scene_helper.dart'; +import 'package:syncrow_app/features/scene/model/scene_static_function.dart'; +import 'package:syncrow_app/features/scene/widgets/alert_dialog_functions_body.dart'; +import 'package:syncrow_app/features/scene/widgets/alert_dialog_temperature_body.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/light_divider.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart'; -import 'package:syncrow_app/generated/assets.dart'; import 'package:syncrow_app/utils/context_extension.dart'; import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; -import 'package:syncrow_app/utils/resource_manager/strings_manager.dart'; class DeviceFunctionsView extends StatelessWidget with SceneHelper { const DeviceFunctionsView({super.key}); @override Widget build(BuildContext context) { + /// this whole widget i need to revamp it later + /// + /// static functions based on type final device = ModalRoute.of(context)?.settings.arguments as DeviceModel; - // var functions = []; - // if (device.functions.isNotEmpty) { - // functions = getFunctionsWithIcons( - // type: device.productType, functions: device.functions); - // } + + /// static custom functions based on type + /// used for now until later backend fixes + List functions = []; + if (device.functions.isNotEmpty) { + functions = getFunctionsWithIcons( + type: device.productType, functions: device.functions); + } return DefaultScaffold( - title: '${device.name} ${StringsManager.functions}', - actions: [ - TextButton( - onPressed: () {}, + title: getTitle(type: device.productType), + actions: [ + TextButton( + onPressed: () {}, + child: BodyMedium( + text: 'Save', + fontWeight: FontWeight.normal, + fontColor: ColorsManager.secondaryColor.withOpacity(0.6), + ), + ), + ], + leading: TextButton( + onPressed: () => Navigator.pop(context), child: BodyMedium( - text: 'Save', + text: 'Cancel', fontWeight: FontWeight.normal, - fontColor: ColorsManager.secondaryColor.withOpacity(0.6), + fontColor: ColorsManager.textPrimaryColor.withOpacity(0.6), ), ), - ], - leading: TextButton( - onPressed: () => Navigator.pop(context), - child: BodyMedium( - text: 'Cancel', - fontWeight: FontWeight.normal, - fontColor: ColorsManager.textPrimaryColor.withOpacity(0.6), - ), - ), - leadingWidth: 80, - padding: EdgeInsets.zero, - child: DefaultContainer( - margin: const EdgeInsets.only(top: 24), - child: ListView.builder( - shrinkWrap: true, - itemCount: device.functions.length, - itemBuilder: (context, index) { - final function = device.functions[index]; - return SceneListTile( - assetPath: null, - minLeadingWidth: 40, - leadingWidget: Image.asset( - Assets.assetsIconsLogo, - width: 20, - ), - titleWidget: BodyMedium( - text: function.code ?? '', - style: context.titleSmall.copyWith( - color: ColorsManager.secondaryTextColor, - fontWeight: FontWeight.w400, - fontSize: 15, + leadingWidth: 80, + padding: EdgeInsets.zero, + child: Padding( + padding: const EdgeInsets.only(top: 24.0), + child: ListView.builder( + shrinkWrap: true, + itemCount: functions.length, + padding: EdgeInsets.zero, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (context, index) { + return DefaultContainer( + padding: index == 0 + ? const EdgeInsets.only(top: 8) + : index == functions.length - 1 + ? const EdgeInsets.only(bottom: 8) + : EdgeInsets.zero, + margin: EdgeInsets.zero, + borderRadius: index == 0 + ? const BorderRadius.only( + topLeft: Radius.circular(20), + topRight: Radius.circular(20)) + : index == functions.length - 1 + ? const BorderRadius.only( + bottomLeft: Radius.circular(20), + bottomRight: Radius.circular(20)) + : BorderRadius.zero, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + SceneListTile( + iconsSize: 32, + minLeadingWidth: 20, + assetPath: functions[index].icon, + titleString: functions[index].name, + trailingWidget: const Row( + mainAxisSize: MainAxisSize.min, + children: [ + /// selected value or the default value + // BodyMedium(text: ), + Icon( + Icons.arrow_forward_ios_rounded, + color: ColorsManager.greyColor, + size: 16, + ), + ], + ), + onPressed: () { + context.customAlertDialog( + alertBody: functions[index].code == 'temp_set' + ? AlertDialogTemperatureBody( + index: index, functions: functions) + : AlertDialogFunctionsOperationsBody( + index: index, functions: functions), + title: functions[index].name, + onConfirm: () {}, + ); + }, + ), + index != functions.length - 1 + ? SizedBox( + width: context.width * 0.8, + child: const LightDivider()) + : const SizedBox(), + ], ), - ), - trailingWidget: const Icon( - Icons.arrow_forward_ios_rounded, - color: ColorsManager.greyColor, - size: 16, - ), - onPressed: () {}, - ); - }, - ), - ), - ); + ); + }, + ), + )); } } diff --git a/lib/features/scene/view/scene_control_devices.dart b/lib/features/scene/view/scene_control_devices.dart index 878e8f3..090f381 100644 --- a/lib/features/scene/view/scene_control_devices.dart +++ b/lib/features/scene/view/scene_control_devices.dart @@ -71,6 +71,15 @@ class _SceneControlDevicesViewState extends State return DefaultScaffold( title: StringsManager.createScene, padding: EdgeInsets.zero, + leading: IconButton( + onPressed: () { + Navigator.pop(context); + Navigator.pop(context); + }, + icon: const Icon( + Icons.arrow_back_ios, + ), + ), child: SceneDevicesBody(tabController: _tabController, rooms: rooms), ); } diff --git a/lib/features/scene/widgets/alert_dialog_countdown.dart b/lib/features/scene/widgets/alert_dialog_countdown.dart new file mode 100644 index 0000000..03a041e --- /dev/null +++ b/lib/features/scene/widgets/alert_dialog_countdown.dart @@ -0,0 +1,19 @@ +import 'package:flutter/material.dart'; + +class AlertDialogCountdown extends StatefulWidget { + const AlertDialogCountdown({super.key}); + + @override + State createState() => _AlertDialogCountdownState(); +} + +class _AlertDialogCountdownState extends State { + @override + Widget build(BuildContext context) { + return Row( + children: [ + + ], + ); + } +} diff --git a/lib/features/scene/widgets/alert_dialog_functions_body.dart b/lib/features/scene/widgets/alert_dialog_functions_body.dart new file mode 100644 index 0000000..a4237a1 --- /dev/null +++ b/lib/features/scene/widgets/alert_dialog_functions_body.dart @@ -0,0 +1,57 @@ +import 'package:flutter/material.dart'; +import 'package:syncrow_app/features/scene/model/scene_static_function.dart'; +import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart'; + +class AlertDialogFunctionsOperationsBody extends StatefulWidget { + const AlertDialogFunctionsOperationsBody({ + super.key, + required this.functions, + required this.index, + }); + + final List functions; + final int index; + + @override + State createState() => + _AlertDialogFunctionsOperationsBodyState(); +} + +class _AlertDialogFunctionsOperationsBodyState + extends State { + String? groupValue = ""; + @override + Widget build(BuildContext context) { + return SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + ...widget.functions[widget.index].operationalValues.map( + (operation) => SceneListTile( + iconsSize: 22, + minLeadingWidth: 15, + padding: const EdgeInsets.symmetric(horizontal: 16), + assetPath: operation.icon, + titleString: operation.value, + textAlign: TextAlign.start, + trailingWidget: Radio( + value: operation.value, + groupValue: groupValue, + onChanged: (value) { + setState(() { + groupValue = value; + }); + }, + ), + onPressed: () { + setState(() { + groupValue = operation.value; + }); + }, + ), + ), + ], + ), + ); + } +} diff --git a/lib/features/scene/widgets/alert_dialog_temperature_body.dart b/lib/features/scene/widgets/alert_dialog_temperature_body.dart new file mode 100644 index 0000000..df80d43 --- /dev/null +++ b/lib/features/scene/widgets/alert_dialog_temperature_body.dart @@ -0,0 +1,82 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:syncrow_app/features/scene/model/scene_static_function.dart'; +import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart'; +import 'package:syncrow_app/features/shared_widgets/text_widgets/title_medium.dart'; +import 'package:syncrow_app/generated/assets.dart'; +import 'package:syncrow_app/utils/context_extension.dart'; +import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; + +class AlertDialogTemperatureBody extends StatefulWidget { + const AlertDialogTemperatureBody({ + super.key, + required this.index, + required this.functions, + }); + + final List functions; + final int index; + + @override + State createState() => + _AlertDialogTemperatureBodyState(); +} + +class _AlertDialogTemperatureBodyState + extends State { + double temperature = 16; + @override + Widget build(BuildContext context) { + return ListTile( + contentPadding: const EdgeInsets.symmetric(horizontal: 32), + leading: IconButton( + onPressed: () { + setState(() { + temperature--; + }); + }, + icon: const Icon( + Icons.remove, + size: 32, + color: ColorsManager.greyColor, + )), + title: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + TitleMedium( + text: temperature.toString(), + style: context.titleMedium.copyWith( + color: ColorsManager.primaryColorWithOpacity, + fontSize: 30, + )), + const SizedBox(width: 4), + Padding( + padding: const EdgeInsets.only(bottom: 8.0), + child: SvgPicture.asset( + Assets.assetsCelsiusDegrees, + alignment: Alignment.topCenter, + width: 32, + ), + ), + ], + ), + subtitle: BodyLarge( + text: widget.functions[widget.index].operationalValues[0].value, + textAlign: TextAlign.center, + ), + trailing: IconButton( + onPressed: () { + setState(() { + temperature++; + }); + }, + icon: const Icon( + Icons.add, + size: 32, + color: ColorsManager.greyColor, + )), + ); + } +} diff --git a/lib/features/scene/widgets/bottom_sheet_widget.dart b/lib/features/scene/widgets/bottom_sheet_widget.dart index ba81a39..c435722 100644 --- a/lib/features/scene/widgets/bottom_sheet_widget.dart +++ b/lib/features/scene/widgets/bottom_sheet_widget.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.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/light_divider.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart'; @@ -75,17 +74,7 @@ class CustomBottomSheetWidget extends StatelessWidget { size: 16, color: ColorsManager.greyColor, ), - onPressed: () { - context.customAlertDialog( - height: 300, - child: Material( - child: DefaultContainer( - width: context.width * 0.8, - child: Text('Comming soon'), - ), - ), - ); - }, + onPressed: () {}, ), ], ), diff --git a/lib/features/scene/widgets/scene_list_tile.dart b/lib/features/scene/widgets/scene_list_tile.dart index c667cf0..4cb6f42 100644 --- a/lib/features/scene/widgets/scene_list_tile.dart +++ b/lib/features/scene/widgets/scene_list_tile.dart @@ -11,7 +11,6 @@ class SceneListTile extends StatelessWidget { super.key, this.assetPath, this.titleString, - this.subtitle, this.leadingWidget, this.trailingWidget, this.padding, @@ -20,10 +19,14 @@ class SceneListTile extends StatelessWidget { this.assetHeight, this.minLeadingWidth, this.titleWidget, + this.subtitleString, + this.subtitleWidget, + this.iconsSize, }); final String? assetPath; final String? titleString; - final String? subtitle; + final Widget? subtitleWidget; + final String? subtitleString; final Widget? leadingWidget; final Widget? trailingWidget; final EdgeInsetsGeometry? padding; @@ -32,6 +35,7 @@ class SceneListTile extends StatelessWidget { final double? assetHeight; final double? minLeadingWidth; final Widget? titleWidget; + final double? iconsSize; @override Widget build(BuildContext context) { @@ -39,11 +43,15 @@ class SceneListTile extends StatelessWidget { minLeadingWidth: minLeadingWidth ?? 40, leading: leadingWidget ?? (assetPath != null - ? SvgPicture.asset( - assetPath ?? Assets.assetsImagesLogo, - width: 20, - height: assetHeight ?? 32, - fit: BoxFit.fitWidth, + ? SizedBox( + width: iconsSize, + child: SvgPicture.asset( + assetPath ?? Assets.assetsImagesLogo, + width: 20, + height: assetHeight ?? 32, + alignment: Alignment.center, + fit: BoxFit.fill, + ), ) : null), trailing: trailingWidget, @@ -54,13 +62,15 @@ class SceneListTile extends StatelessWidget { textAlign: textAlign, style: context.bodyMedium.copyWith(fontSize: 15), ), - subtitle: subtitle == null - ? null - : BodySmall( - text: subtitle!, - style: context.bodySmall.copyWith( - fontWeight: FontWeight.w400, color: ColorsManager.greyColor), - ), + subtitle: subtitleWidget ?? + (subtitleString?.isNotEmpty == true + ? BodySmall( + text: subtitleString ?? '', + style: context.bodySmall.copyWith( + fontWeight: FontWeight.w400, + color: ColorsManager.greyColor), + ) + : null), onTap: onPressed, ); } diff --git a/lib/features/shared_widgets/default_container.dart b/lib/features/shared_widgets/default_container.dart index dc4a966..e0a71b0 100644 --- a/lib/features/shared_widgets/default_container.dart +++ b/lib/features/shared_widgets/default_container.dart @@ -11,6 +11,7 @@ class DefaultContainer extends StatelessWidget { this.margin, this.padding, this.onTap, + this.borderRadius, }); final double? height; @@ -21,6 +22,7 @@ class DefaultContainer extends StatelessWidget { final EdgeInsets? padding; final Color? color; final Function()? onTap; + final BorderRadius? borderRadius; @override Widget build(BuildContext context) { return InkWell( @@ -33,7 +35,7 @@ class DefaultContainer extends StatelessWidget { constraints: boxConstraints, decoration: BoxDecoration( color: color ?? Colors.white, - borderRadius: BorderRadius.circular(20), + borderRadius: borderRadius ?? BorderRadius.circular(20), ), padding: padding ?? const EdgeInsets.all(10), child: child, diff --git a/lib/features/shared_widgets/default_scaffold.dart b/lib/features/shared_widgets/default_scaffold.dart index 1829ebe..cc0bc80 100644 --- a/lib/features/shared_widgets/default_scaffold.dart +++ b/lib/features/shared_widgets/default_scaffold.dart @@ -43,10 +43,12 @@ class DefaultScaffold extends StatelessWidget { AppBar( backgroundColor: Colors.transparent, centerTitle: true, - title: BodyLarge( - text: title ?? "", - fontColor: ColorsManager.secondaryColor, - fontWeight: FontsManager.bold, + title: FittedBox( + child: BodyLarge( + text: title ?? "", + fontColor: ColorsManager.secondaryColor, + fontWeight: FontsManager.bold, + ), ), actions: actions, leading: leading, diff --git a/lib/generated/assets.dart b/lib/generated/assets.dart index 89aefad..7040c17 100644 --- a/lib/generated/assets.dart +++ b/lib/generated/assets.dart @@ -765,4 +765,96 @@ class Assets { /// Assets for assetsImagesWindow /// assets/images/Window.png static const String assetsImagesWindow = "assets/images/Window.png"; + + static const String assetsSensitivityFunction = + "assets/icons/functions_icons/sensitivity.svg"; + + //assets/icons/functions_icons/sesitivity_operation_icon.svg + static const String assetsSensitivityOperationIcon = + "assets/icons/functions_icons/sesitivity_operation_icon.svg"; + + //assets/icons/functions_icons/ac_power.svg + + static const String assetsAcPower = + "assets/icons/functions_icons/ac_power.svg"; + + //assets/icons/functions_icons/ac_power_off.svg + + static const String assetsAcPowerOFF = + "assets/icons/functions_icons/ac_power_off.svg"; + + //assets/icons/functions_icons/child_lock.svg + + static const String assetsChildLock = + "assets/icons/functions_icons/child_lock.svg"; + + //assets/icons/functions_icons/cooling.svg + + static const String assetsFreezing = + "assets/icons/functions_icons/freezing.svg"; + + //assets/icons/functions_icons/fan_speed.svg + + static const String assetsFanSpeed = + "assets/icons/functions_icons/fan_speed.svg"; + + //assets/icons/functions_icons/ac_cooling.svg + + static const String assetsAcCooling = + "assets/icons/functions_icons/ac_cooling.svg"; + + //assets/icons/functions_icons/ac_heating.svg + + static const String assetsAcHeating = + "assets/icons/functions_icons/ac_heating.svg"; + + //assets/icons/functions_icons/celsius_degrees.svg + + static const String assetsCelsiusDegrees = + "assets/icons/functions_icons/celsius_degrees.svg"; + + //assets/icons/functions_icons/tempreture.svg + + static const String assetsTempreture = + "assets/icons/functions_icons/tempreture.svg"; + + //assets/icons/functions_icons/ac_fan_low.svg + + static const String assetsAcFanLow = + "assets/icons/functions_icons/ac_fan_low.svg"; + + //assets/icons/functions_icons/ac_fan_middle.svg + + static const String assetsAcFanMiddle = + "assets/icons/functions_icons/ac_fan_middle.svg"; + + //assets/icons/functions_icons/ac_fan_high.svg + + static const String assetsAcFanHigh = + "assets/icons/functions_icons/ac_fan_high.svg"; + + //assets/icons/functions_icons/ac_fan_auto.svg + + static const String assetsAcFanAuto = + "assets/icons/functions_icons/ac_fan_auto.svg"; + + //assets/icons/functions_icons/scene_child_lock.svg + + static const String assetsSceneChildLock = + "assets/icons/functions_icons/scene_child_lock.svg"; + + //assets/icons/functions_icons/scene_child_unlock.svg + + static const String assetsSceneChildUnlock = + "assets/icons/functions_icons/scene_child_unlock.svg"; + + //assets/icons/functions_icons/scene_refresh.svg + + static const String assetsSceneRefresh = + "assets/icons/functions_icons/scene_refresh.svg"; + + //assets/icons/functions_icons/light_countdown.svg + + static const String assetsLightCountdown = + "assets/icons/functions_icons/light_countdown.svg"; } diff --git a/lib/utils/context_extension.dart b/lib/utils/context_extension.dart index c0aa079..77d6a50 100644 --- a/lib/utils/context_extension.dart +++ b/lib/utils/context_extension.dart @@ -1,5 +1,8 @@ import 'package:flutter/material.dart'; import 'package:syncrow_app/features/shared_widgets/bottom_sheet/custom_bottom_sheet.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/utils/resource_manager/font_manager.dart'; extension ContextExtension on BuildContext { Future goTo(String newRouteName) async { @@ -44,11 +47,90 @@ extension ContextExtension on BuildContext { ); } - void customAlertDialog({required Widget child, required double height}) { + void customAlertDialog( + {required Widget alertBody, + required String title, + required Function()? onConfirm}) { showDialog( context: this, builder: (BuildContext context) { - return Dialog(child: SizedBox(height: height, child: child)); + return AlertDialog( + contentPadding: EdgeInsets.zero, + content: Container( + width: MediaQuery.sizeOf(context).width, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(20), + ), + padding: const EdgeInsets.only(top: 20), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + /// header widget + BodyMedium( + text: title, + style: context.bodyMedium.copyWith( + color: ColorsManager.primaryColorWithOpacity, + fontWeight: FontsManager.extraBold, + ), + ), + Padding( + padding: const EdgeInsets.symmetric( + vertical: 15, + horizontal: 50, + ), + child: Container( + height: 1, + width: double.infinity, + color: ColorsManager.greyColor, + ), + ), + + /// custom body content + alertBody, + + /// Footer buttons + Container( + height: 1, + width: double.infinity, + color: ColorsManager.greyColor, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + InkWell( + onTap: () { + Navigator.pop(context); + }, + child: Center( + child: BodyMedium( + text: 'Cancel', + style: context.bodyMedium + .copyWith(color: ColorsManager.greyColor), + ), + ), + ), + Container( + height: 50, + width: 1, + color: ColorsManager.greyColor, + ), + InkWell( + onTap: onConfirm, + child: Center( + child: BodyMedium( + text: 'Confirm', + style: context.bodyMedium.copyWith( + color: ColorsManager.primaryColorWithOpacity), + ), + ), + ), + ], + ) + ], + ), + ), + ); }, ); } diff --git a/pubspec.yaml b/pubspec.yaml index 0da1da4..3027c5d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -72,6 +72,7 @@ flutter: - assets/icons/MenuIcons/MessagesCenterIcons/ - assets/icons/MenuIcons/SecurityAndPrivacyIcons/ - assets/icons/curtainsIcon/ + - assets/icons/functions_icons/ fonts: - family: Aftika fonts: