Merge pull request #194 from SyncrowIOT/SP-1448-FE-Use-SliderValueSelector-widget-for-all-slider-widgets-in-Web-Routine

add step parameter in onTapFunction.
This commit is contained in:
mohammadnemer1
2025-05-19 11:37:56 +03:00
committed by GitHub
22 changed files with 938 additions and 728 deletions
+1
View File
@@ -10,6 +10,7 @@
analyzer: analyzer:
errors: errors:
constant_identifier_names: ignore constant_identifier_names: ignore
overridden_fields: ignore
include: package:flutter_lints/flutter.yaml include: package:flutter_lints/flutter.yaml
linter: linter:
@@ -26,8 +26,10 @@ class FunctionBloc extends Bloc<FunctionBlocEvent, FunctionBlocState> {
functionCode: event.functionData.functionCode, functionCode: event.functionData.functionCode,
operationName: event.functionData.operationName, operationName: event.functionData.operationName,
value: event.functionData.value ?? existingData.value, value: event.functionData.value ?? existingData.value,
valueDescription: event.functionData.valueDescription ?? existingData.valueDescription, valueDescription: event.functionData.valueDescription ??
existingData.valueDescription,
condition: event.functionData.condition ?? existingData.condition, condition: event.functionData.condition ?? existingData.condition,
step: event.functionData.step ?? existingData.step,
); );
} else { } else {
functions.clear(); functions.clear();
@@ -59,8 +61,10 @@ class FunctionBloc extends Bloc<FunctionBlocEvent, FunctionBlocState> {
); );
} }
FutureOr<void> _onSelectFunction(SelectFunction event, Emitter<FunctionBlocState> emit) { FutureOr<void> _onSelectFunction(
SelectFunction event, Emitter<FunctionBlocState> emit) {
emit(state.copyWith( emit(state.copyWith(
selectedFunction: event.functionCode, selectedOperationName: event.operationName)); selectedFunction: event.functionCode,
selectedOperationName: event.operationName));
} }
} }
+19 -17
View File
@@ -14,6 +14,10 @@ abstract class ACFunction extends DeviceFunction<AcStatusModel> {
required super.operationName, required super.operationName,
required super.icon, required super.icon,
required this.type, required this.type,
super.step,
super.unit,
super.max,
super.min,
}); });
List<ACOperationalValue> getOperationalValues(); List<ACOperationalValue> getOperationalValues();
@@ -75,26 +79,24 @@ class ModeFunction extends ACFunction {
} }
class TempSetFunction extends ACFunction { class TempSetFunction extends ACFunction {
final int min; TempSetFunction({
final int max; required super.deviceId,
final int step; required super.deviceName,
required super.type,
TempSetFunction( }) : super(
{required super.deviceId, required super.deviceName, required type})
: min = 160,
max = 300,
step = 1,
super(
code: 'temp_set', code: 'temp_set',
operationName: 'Set Temperature', operationName: 'Set Temperature',
icon: Assets.assetsTempreture, icon: Assets.assetsTempreture,
type: type, min: 200,
max: 300,
step: 1,
unit: "°C",
); );
@override @override
List<ACOperationalValue> getOperationalValues() { List<ACOperationalValue> getOperationalValues() {
List<ACOperationalValue> values = []; List<ACOperationalValue> values = [];
for (int temp = min; temp <= max; temp += step) { for (int temp = min!.toInt(); temp <= max!; temp += step!.toInt()) {
values.add(ACOperationalValue( values.add(ACOperationalValue(
icon: Assets.assetsTempreture, icon: Assets.assetsTempreture,
description: "${temp / 10}°C", description: "${temp / 10}°C",
@@ -104,7 +106,6 @@ class TempSetFunction extends ACFunction {
return values; return values;
} }
} }
class LevelFunction extends ACFunction { class LevelFunction extends ACFunction {
LevelFunction( LevelFunction(
{required super.deviceId, required super.deviceName, required type}) {required super.deviceId, required super.deviceName, required type})
@@ -166,9 +167,10 @@ class ChildLockFunction extends ACFunction {
} }
class CurrentTempFunction extends ACFunction { class CurrentTempFunction extends ACFunction {
final int min; final double min;
final int max; final double max;
final int step; final double step;
final String unit = "°C";
CurrentTempFunction( CurrentTempFunction(
{required super.deviceId, required super.deviceName, required type}) {required super.deviceId, required super.deviceName, required type})
@@ -185,7 +187,7 @@ class CurrentTempFunction extends ACFunction {
@override @override
List<ACOperationalValue> getOperationalValues() { List<ACOperationalValue> getOperationalValues() {
List<ACOperationalValue> values = []; List<ACOperationalValue> values = [];
for (int temp = min; temp <= max; temp += step) { for (int temp = min.toInt(); temp <= max; temp += step.toInt()) {
values.add(ACOperationalValue( values.add(ACOperationalValue(
icon: Assets.currentTemp, icon: Assets.currentTemp,
description: "${temp / 10}°C", description: "${temp / 10}°C",
@@ -6,10 +6,12 @@ class CpsOperationalValue {
final String description; final String description;
final dynamic value; final dynamic value;
CpsOperationalValue({ CpsOperationalValue({
required this.icon, required this.icon,
required this.description, required this.description,
required this.value, required this.value,
}); });
} }
@@ -94,9 +96,9 @@ final class CpsSensitivityFunction extends CpsFunctions {
icon: Assets.sensitivity, icon: Assets.sensitivity,
); );
final int min; final double min;
final int max; final double max;
final int step; final double step;
static const _images = <String>[ static const _images = <String>[
Assets.sensitivityFeature1, Assets.sensitivityFeature1,
@@ -115,10 +117,10 @@ final class CpsSensitivityFunction extends CpsFunctions {
@override @override
List<CpsOperationalValue> getOperationalValues() { List<CpsOperationalValue> getOperationalValues() {
final values = <CpsOperationalValue>[]; final values = <CpsOperationalValue>[];
for (var value = min; value <= max; value += step) { for (var value = min; value <= max; value += step.toInt()) {
values.add( values.add(
CpsOperationalValue( CpsOperationalValue(
icon: _images[value], icon: _images[value.toInt()],
description: '$value', description: '$value',
value: value, value: value,
), ),
@@ -142,9 +144,9 @@ final class CpsMovingSpeedFunction extends CpsFunctions {
icon: Assets.speedoMeter, icon: Assets.speedoMeter,
); );
final int min; final double min;
final int max; final double max;
final int step; final double step;
@override @override
List<CpsOperationalValue> getOperationalValues() { List<CpsOperationalValue> getOperationalValues() {
@@ -173,9 +175,9 @@ final class CpsSpatialStaticValueFunction extends CpsFunctions {
icon: Assets.spatialStaticValue, icon: Assets.spatialStaticValue,
); );
final int min; final double min;
final int max; final double max;
final int step; final double step;
@override @override
List<CpsOperationalValue> getOperationalValues() { List<CpsOperationalValue> getOperationalValues() {
@@ -204,9 +206,9 @@ final class CpsSpatialMotionValueFunction extends CpsFunctions {
icon: Assets.spatialMotionValue, icon: Assets.spatialMotionValue,
); );
final int min; final double min;
final int max; final double max;
final int step; final double step;
@override @override
List<CpsOperationalValue> getOperationalValues() { List<CpsOperationalValue> getOperationalValues() {
@@ -375,9 +377,9 @@ final class CpsPresenceJudgementThrsholdFunction extends CpsFunctions {
icon: Assets.presenceJudgementThrshold, icon: Assets.presenceJudgementThrshold,
); );
final int min; final double min;
final int max; final double max;
final int step; final double step;
@override @override
List<CpsOperationalValue> getOperationalValues() { List<CpsOperationalValue> getOperationalValues() {
@@ -406,9 +408,9 @@ final class CpsMotionAmplitudeTriggerThresholdFunction extends CpsFunctions {
icon: Assets.presenceJudgementThrshold, icon: Assets.presenceJudgementThrshold,
); );
final int min; final double min;
final int max; final double max;
final int step; final double step;
@override @override
List<CpsOperationalValue> getOperationalValues() { List<CpsOperationalValue> getOperationalValues() {
@@ -4,6 +4,11 @@ abstract class DeviceFunction<T> {
final String code; final String code;
final String operationName; final String operationName;
final String icon; final String icon;
final double? step;
final String? unit;
final double? max;
final double? min;
DeviceFunction({ DeviceFunction({
required this.deviceId, required this.deviceId,
@@ -11,6 +16,10 @@ abstract class DeviceFunction<T> {
required this.code, required this.code,
required this.operationName, required this.operationName,
required this.icon, required this.icon,
this.step,
this.unit,
this.max,
this.min,
}); });
} }
@@ -22,6 +31,10 @@ class DeviceFunctionData {
final dynamic value; final dynamic value;
final String? condition; final String? condition;
final String? valueDescription; final String? valueDescription;
final double? step;
final String? unit;
final double? max;
final double? min;
DeviceFunctionData({ DeviceFunctionData({
required this.entityId, required this.entityId,
@@ -31,6 +44,10 @@ class DeviceFunctionData {
required this.value, required this.value,
this.condition, this.condition,
this.valueDescription, this.valueDescription,
this.step,
this.unit,
this.max,
this.min,
}); });
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
@@ -42,6 +59,10 @@ class DeviceFunctionData {
'value': value, 'value': value,
if (condition != null) 'condition': condition, if (condition != null) 'condition': condition,
if (valueDescription != null) 'valueDescription': valueDescription, if (valueDescription != null) 'valueDescription': valueDescription,
if (step != null) 'step': step,
if (unit != null) 'unit': unit,
if (max != null) 'max': max,
if (min != null) 'min': min,
}; };
} }
@@ -54,6 +75,10 @@ class DeviceFunctionData {
value: json['value'], value: json['value'],
condition: json['condition'], condition: json['condition'],
valueDescription: json['valueDescription'], valueDescription: json['valueDescription'],
step: json['step']?.toDouble(),
unit: json['unit'],
max: json['max']?.toDouble(),
min: json['min']?.toDouble(),
); );
} }
@@ -68,7 +93,11 @@ class DeviceFunctionData {
other.operationName == operationName && other.operationName == operationName &&
other.value == value && other.value == value &&
other.condition == condition && other.condition == condition &&
other.valueDescription == valueDescription; other.valueDescription == valueDescription &&
other.step == step &&
other.unit == unit &&
other.max == max &&
other.min == min;
} }
@override @override
@@ -79,6 +108,10 @@ class DeviceFunctionData {
operationName.hashCode ^ operationName.hashCode ^
value.hashCode ^ value.hashCode ^
condition.hashCode ^ condition.hashCode ^
valueDescription.hashCode; valueDescription.hashCode ^
step.hashCode ^
unit.hashCode ^
max.hashCode ^
min.hashCode;
} }
} }
@@ -20,12 +20,11 @@ abstract class FlushFunctions
} }
class FlushPresenceDelayFunction extends FlushFunctions { class FlushPresenceDelayFunction extends FlushFunctions {
final int min;
FlushPresenceDelayFunction({ FlushPresenceDelayFunction({
required super.deviceId, required super.deviceId,
required super.deviceName, required super.deviceName,
required super.type, required super.type,
}) : min = 0, }) :
super( super(
code: FlushMountedPresenceSensorModel.codePresenceState, code: FlushMountedPresenceSensorModel.codePresenceState,
operationName: 'Presence State', operationName: 'Presence State',
@@ -50,9 +49,9 @@ class FlushPresenceDelayFunction extends FlushFunctions {
} }
class FlushSensiReduceFunction extends FlushFunctions { class FlushSensiReduceFunction extends FlushFunctions {
final int min; final double min;
final int max; final double max;
final int step; final double step;
FlushSensiReduceFunction({ FlushSensiReduceFunction({
required super.deviceId, required super.deviceId,
@@ -80,8 +79,8 @@ class FlushSensiReduceFunction extends FlushFunctions {
} }
class FlushNoneDelayFunction extends FlushFunctions { class FlushNoneDelayFunction extends FlushFunctions {
final int min; final double min;
final int max; final double max;
final String unit; final String unit;
FlushNoneDelayFunction({ FlushNoneDelayFunction({
@@ -110,9 +109,9 @@ class FlushNoneDelayFunction extends FlushFunctions {
} }
class FlushIlluminanceFunction extends FlushFunctions { class FlushIlluminanceFunction extends FlushFunctions {
final int min; final double min;
final int max; final double max;
final int step; final double step;
FlushIlluminanceFunction({ FlushIlluminanceFunction({
required super.deviceId, required super.deviceId,
@@ -130,7 +129,7 @@ class FlushIlluminanceFunction extends FlushFunctions {
@override @override
List<FlushOperationalValue> getOperationalValues() { List<FlushOperationalValue> getOperationalValues() {
List<FlushOperationalValue> values = []; List<FlushOperationalValue> values = [];
for (int lux = min; lux <= max; lux += step) { for (int lux = min.toInt(); lux <= max; lux += step.toInt()) {
values.add(FlushOperationalValue( values.add(FlushOperationalValue(
icon: Assets.IlluminanceIcon, icon: Assets.IlluminanceIcon,
description: "$lux Lux", description: "$lux Lux",
@@ -142,9 +141,9 @@ class FlushIlluminanceFunction extends FlushFunctions {
} }
class FlushOccurDistReduceFunction extends FlushFunctions { class FlushOccurDistReduceFunction extends FlushFunctions {
final int min; final double min;
final int max; final double max;
final int step; final double step;
FlushOccurDistReduceFunction({ FlushOccurDistReduceFunction({
required super.deviceId, required super.deviceId,
@@ -173,9 +172,9 @@ class FlushOccurDistReduceFunction extends FlushFunctions {
// ==== then functions ==== // ==== then functions ====
class FlushSensitivityFunction extends FlushFunctions { class FlushSensitivityFunction extends FlushFunctions {
final int min; final double min;
final int max; final double max;
final int step; final double step;
FlushSensitivityFunction({ FlushSensitivityFunction({
required super.deviceId, required super.deviceId,
@@ -203,9 +202,9 @@ class FlushSensitivityFunction extends FlushFunctions {
} }
class FlushNearDetectionFunction extends FlushFunctions { class FlushNearDetectionFunction extends FlushFunctions {
final int min; final double min;
final double max; final double max;
final int step; final double step;
final String unit; final String unit;
FlushNearDetectionFunction({ FlushNearDetectionFunction({
@@ -225,7 +224,7 @@ class FlushNearDetectionFunction extends FlushFunctions {
@override @override
List<FlushOperationalValue> getOperationalValues() { List<FlushOperationalValue> getOperationalValues() {
final values = <FlushOperationalValue>[]; final values = <FlushOperationalValue>[];
for (var value = min; value <= max; value += step) { for (var value = min.toDouble(); value <= max; value += step) {
values.add(FlushOperationalValue( values.add(FlushOperationalValue(
icon: Assets.nobodyTime, icon: Assets.nobodyTime,
description: '$value $unit', description: '$value $unit',
@@ -237,9 +236,9 @@ class FlushNearDetectionFunction extends FlushFunctions {
} }
class FlushMaxDetectDistFunction extends FlushFunctions { class FlushMaxDetectDistFunction extends FlushFunctions {
final int min; final double min;
final int max; final double max;
final int step; final double step;
final String unit; final String unit;
FlushMaxDetectDistFunction({ FlushMaxDetectDistFunction({
@@ -259,7 +258,7 @@ class FlushMaxDetectDistFunction extends FlushFunctions {
@override @override
List<FlushOperationalValue> getOperationalValues() { List<FlushOperationalValue> getOperationalValues() {
final values = <FlushOperationalValue>[]; final values = <FlushOperationalValue>[];
for (var value = min; value <= max; value += step) { for (var value = min; value <= max; value += step.toInt()) {
values.add(FlushOperationalValue( values.add(FlushOperationalValue(
icon: Assets.nobodyTime, icon: Assets.nobodyTime,
description: '$value $unit', description: '$value $unit',
@@ -271,9 +270,9 @@ class FlushMaxDetectDistFunction extends FlushFunctions {
} }
class FlushTargetConfirmTimeFunction extends FlushFunctions { class FlushTargetConfirmTimeFunction extends FlushFunctions {
final int min; final double min;
final int max; final double max;
final int step; final double step;
final String unit; final String unit;
FlushTargetConfirmTimeFunction({ FlushTargetConfirmTimeFunction({
@@ -293,7 +292,7 @@ class FlushTargetConfirmTimeFunction extends FlushFunctions {
@override @override
List<FlushOperationalValue> getOperationalValues() { List<FlushOperationalValue> getOperationalValues() {
final values = <FlushOperationalValue>[]; final values = <FlushOperationalValue>[];
for (var value = min; value <= max; value += step) { for (var value = min.toDouble(); value <= max; value += step) {
values.add(FlushOperationalValue( values.add(FlushOperationalValue(
icon: Assets.nobodyTime, icon: Assets.nobodyTime,
description: '$value $unit', description: '$value $unit',
@@ -305,9 +304,9 @@ class FlushTargetConfirmTimeFunction extends FlushFunctions {
} }
class FlushDisappeDelayFunction extends FlushFunctions { class FlushDisappeDelayFunction extends FlushFunctions {
final int min; final double min;
final int max; final double max;
final int step; final double step;
final String unit; final String unit;
FlushDisappeDelayFunction({ FlushDisappeDelayFunction({
@@ -327,7 +326,7 @@ class FlushDisappeDelayFunction extends FlushFunctions {
@override @override
List<FlushOperationalValue> getOperationalValues() { List<FlushOperationalValue> getOperationalValues() {
final values = <FlushOperationalValue>[]; final values = <FlushOperationalValue>[];
for (var value = min; value <= max; value += step) { for (var value = min.toDouble(); value <= max; value += step) {
values.add(FlushOperationalValue( values.add(FlushOperationalValue(
icon: Assets.nobodyTime, icon: Assets.nobodyTime,
description: '$value $unit', description: '$value $unit',
@@ -339,9 +338,9 @@ class FlushDisappeDelayFunction extends FlushFunctions {
} }
class FlushIndentLevelFunction extends FlushFunctions { class FlushIndentLevelFunction extends FlushFunctions {
final int min; final double min;
final int max; final double max;
final int step; final double step;
final String unit; final String unit;
FlushIndentLevelFunction({ FlushIndentLevelFunction({
@@ -361,7 +360,7 @@ class FlushIndentLevelFunction extends FlushFunctions {
@override @override
List<FlushOperationalValue> getOperationalValues() { List<FlushOperationalValue> getOperationalValues() {
final values = <FlushOperationalValue>[]; final values = <FlushOperationalValue>[];
for (var value = min; value <= max; value += step) { for (var value = min.toDouble(); value <= max; value += step) {
values.add(FlushOperationalValue( values.add(FlushOperationalValue(
icon: Assets.nobodyTime, icon: Assets.nobodyTime,
description: '$value $unit', description: '$value $unit',
@@ -373,9 +372,9 @@ class FlushIndentLevelFunction extends FlushFunctions {
} }
class FlushTriggerLevelFunction extends FlushFunctions { class FlushTriggerLevelFunction extends FlushFunctions {
final int min; final double min;
final int max; final double max;
final int step; final double step;
final String unit; final String unit;
FlushTriggerLevelFunction({ FlushTriggerLevelFunction({
@@ -395,7 +394,7 @@ class FlushTriggerLevelFunction extends FlushFunctions {
@override @override
List<FlushOperationalValue> getOperationalValues() { List<FlushOperationalValue> getOperationalValues() {
final values = <FlushOperationalValue>[]; final values = <FlushOperationalValue>[];
for (var value = min; value <= max; value += step) { for (var value = min.toDouble(); value <= max; value += step) {
values.add(FlushOperationalValue( values.add(FlushOperationalValue(
icon: Assets.nobodyTime, icon: Assets.nobodyTime,
description: '$value $unit', description: '$value $unit',
@@ -20,17 +20,16 @@ abstract class WaterHeaterFunctions
} }
class WHRestartStatusFunction extends WaterHeaterFunctions { class WHRestartStatusFunction extends WaterHeaterFunctions {
final int min;
WHRestartStatusFunction({ WHRestartStatusFunction({
required super.deviceId, required super.deviceId,
required super.deviceName, required super.deviceName,
required super.type, required super.type,
}) : min = 0, }) : super(
super(
code: 'relay_status', code: 'relay_status',
operationName: 'Restart Status', operationName: 'Restart Status',
icon: Assets.refreshStatusIcon, icon: Assets.refreshStatusIcon,
); );
@override @override
List<WaterHeaterOperationalValue> getOperationalValues() { List<WaterHeaterOperationalValue> getOperationalValues() {
@@ -55,13 +54,11 @@ class WHRestartStatusFunction extends WaterHeaterFunctions {
} }
class WHSwitchFunction extends WaterHeaterFunctions { class WHSwitchFunction extends WaterHeaterFunctions {
final int min;
WHSwitchFunction({ WHSwitchFunction({
required super.deviceId, required super.deviceId,
required super.deviceName, required super.deviceName,
required super.type, required super.type,
}) : min = 0, }) : super(
super(
code: 'switch_1', code: 'switch_1',
operationName: 'Switch', operationName: 'Switch',
icon: Assets.assetsAcPower, icon: Assets.assetsAcPower,
@@ -104,12 +101,11 @@ class TimerConfirmTimeFunction extends WaterHeaterFunctions {
} }
class BacklightFunction extends WaterHeaterFunctions { class BacklightFunction extends WaterHeaterFunctions {
final int min;
BacklightFunction({ BacklightFunction({
required super.deviceId, required super.deviceId,
required super.deviceName, required super.deviceName,
required super.type, required super.type,
}) : min = 0, }) :
super( super(
code: 'switch_backlight', code: 'switch_backlight',
operationName: 'Backlight', operationName: 'Backlight',
@@ -4,7 +4,7 @@ import 'package:syncrow_web/pages/routines/models/wps/wps_operational_value.dart
import 'package:syncrow_web/utils/constants/assets.dart'; import 'package:syncrow_web/utils/constants/assets.dart';
abstract class WpsFunctions extends DeviceFunction<WallSensorModel> { abstract class WpsFunctions extends DeviceFunction<WallSensorModel> {
final String type; final String type;
WpsFunctions({ WpsFunctions({
required super.deviceId, required super.deviceId,
@@ -13,6 +13,10 @@ abstract class WpsFunctions extends DeviceFunction<WallSensorModel> {
required super.operationName, required super.operationName,
required super.icon, required super.icon,
required this.type, required this.type,
super.step,
super.unit,
super.max,
super.min,
}); });
List<WpsOperationalValue> getOperationalValues(); List<WpsOperationalValue> getOperationalValues();
@@ -20,9 +24,13 @@ abstract class WpsFunctions extends DeviceFunction<WallSensorModel> {
// For far_detection (75-600cm in 75cm steps) // For far_detection (75-600cm in 75cm steps)
class FarDetectionFunction extends WpsFunctions { class FarDetectionFunction extends WpsFunctions {
final int min;
final int max; final double min;
final int step; @override
final double max;
@override
final double step;
@override
final String unit; final String unit;
FarDetectionFunction( FarDetectionFunction(
@@ -41,7 +49,7 @@ class FarDetectionFunction extends WpsFunctions {
@override @override
List<WpsOperationalValue> getOperationalValues() { List<WpsOperationalValue> getOperationalValues() {
final values = <WpsOperationalValue>[]; final values = <WpsOperationalValue>[];
for (var value = min; value <= max; value += step) { for (var value = min; value <= max; value += step.toInt()) {
values.add(WpsOperationalValue( values.add(WpsOperationalValue(
icon: Assets.currentDistanceIcon, icon: Assets.currentDistanceIcon,
description: '$value $unit', description: '$value $unit',
@@ -54,9 +62,9 @@ class FarDetectionFunction extends WpsFunctions {
// For presence_time (0-65535 minutes) // For presence_time (0-65535 minutes)
class PresenceTimeFunction extends WpsFunctions { class PresenceTimeFunction extends WpsFunctions {
final int min; final double min;
final int max; final double max;
final int step; final double step;
final String unit; final String unit;
PresenceTimeFunction( PresenceTimeFunction(
@@ -86,9 +94,9 @@ class PresenceTimeFunction extends WpsFunctions {
// For motion_sensitivity_value (1-5 levels) // For motion_sensitivity_value (1-5 levels)
class MotionSensitivityFunction extends WpsFunctions { class MotionSensitivityFunction extends WpsFunctions {
final int min; final double min;
final int max; final double max;
final int step; final double step;
MotionSensitivityFunction( MotionSensitivityFunction(
{required super.deviceId, required super.deviceName, required type}) {required super.deviceId, required super.deviceName, required type})
@@ -116,9 +124,9 @@ class MotionSensitivityFunction extends WpsFunctions {
} }
class MotionLessSensitivityFunction extends WpsFunctions { class MotionLessSensitivityFunction extends WpsFunctions {
final int min; final double min;
final int max; final double max;
final int step; final double step;
MotionLessSensitivityFunction( MotionLessSensitivityFunction(
{required super.deviceId, required super.deviceName, required type}) {required super.deviceId, required super.deviceName, required type})
@@ -171,8 +179,8 @@ class IndicatorFunction extends WpsFunctions {
} }
class NoOneTimeFunction extends WpsFunctions { class NoOneTimeFunction extends WpsFunctions {
final int min; final double min;
final int max; final double max;
final String unit; final String unit;
NoOneTimeFunction( NoOneTimeFunction(
@@ -225,9 +233,9 @@ class PresenceStateFunction extends WpsFunctions {
} }
class CurrentDistanceFunction extends WpsFunctions { class CurrentDistanceFunction extends WpsFunctions {
final int min; final double min;
final int max; final double max;
final int step; final double step;
CurrentDistanceFunction( CurrentDistanceFunction(
{required super.deviceId, required super.deviceName, required type}) {required super.deviceId, required super.deviceName, required type})
@@ -244,11 +252,10 @@ class CurrentDistanceFunction extends WpsFunctions {
@override @override
List<WpsOperationalValue> getOperationalValues() { List<WpsOperationalValue> getOperationalValues() {
List<WpsOperationalValue> values = []; List<WpsOperationalValue> values = [];
for (int cm = min; cm <= max; cm += step) { for (int cm = min.toInt(); cm <= max; cm += step.toInt()) {
values.add(WpsOperationalValue( values.add(WpsOperationalValue(
icon: Assets.assetsTempreture, icon: Assets.assetsTempreture,
description: "${cm}CM", description: "${cm}CM",
value: cm, value: cm,
)); ));
} }
@@ -257,9 +264,9 @@ class CurrentDistanceFunction extends WpsFunctions {
} }
class IlluminanceValueFunction extends WpsFunctions { class IlluminanceValueFunction extends WpsFunctions {
final int min; final double min;
final int max; final double max;
final int step; final double step;
IlluminanceValueFunction({ IlluminanceValueFunction({
required super.deviceId, required super.deviceId,
@@ -277,7 +284,7 @@ class IlluminanceValueFunction extends WpsFunctions {
@override @override
List<WpsOperationalValue> getOperationalValues() { List<WpsOperationalValue> getOperationalValues() {
List<WpsOperationalValue> values = []; List<WpsOperationalValue> values = [];
for (int lux = min; lux <= max; lux += step) { for (int lux = min.toInt(); lux <= max; lux += step.toInt()) {
values.add(WpsOperationalValue( values.add(WpsOperationalValue(
icon: Assets.IlluminanceIcon, icon: Assets.IlluminanceIcon,
description: "$lux Lux", description: "$lux Lux",
@@ -0,0 +1,297 @@
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:syncrow_web/pages/routines/widgets/condition_toggle.dart';
import 'package:syncrow_web/pages/routines/widgets/slider_value_selector.dart';
import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/extension/build_context_x.dart';
class CustomRoutinesTextbox extends StatefulWidget {
final String? currentCondition;
final String dialogType;
final (double, double) sliderRange;
final dynamic displayedValue;
final dynamic initialValue;
final void Function(String condition) onConditionChanged;
final void Function(double value) onTextChanged;
final String unit;
final double dividendOfRange;
final double stepIncreaseAmount;
final bool withSpecialChar;
const CustomRoutinesTextbox({
required this.dialogType,
required this.sliderRange,
required this.displayedValue,
required this.initialValue,
required this.onConditionChanged,
required this.onTextChanged,
required this.currentCondition,
required this.unit,
required this.dividendOfRange,
required this.stepIncreaseAmount,
required this.withSpecialChar,
super.key,
});
@override
State<CustomRoutinesTextbox> createState() => _CustomRoutinesTextboxState();
}
class _CustomRoutinesTextboxState extends State<CustomRoutinesTextbox> {
late final TextEditingController _controller;
bool hasError = false;
String? errorMessage;
int getDecimalPlaces(double step) {
String stepStr = step.toString();
if (stepStr.contains('.')) {
List<String> parts = stepStr.split('.');
String decimalPart = parts[1];
decimalPart = decimalPart.replaceAll(RegExp(r'0+$'), '');
return decimalPart.isEmpty ? 0 : decimalPart.length;
} else {
return 0;
}
}
@override
void initState() {
super.initState();
int decimalPlaces = getDecimalPlaces(widget.stepIncreaseAmount);
double initialValue;
if (widget.initialValue != null &&
widget.initialValue is num &&
(widget.initialValue as num) == 0) {
initialValue = 0.0;
} else {
initialValue = double.tryParse(widget.displayedValue) ?? 0.0;
}
_controller = TextEditingController(
text: initialValue.toStringAsFixed(decimalPlaces),
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
void _validateInput(String value) {
final doubleValue = double.tryParse(value);
if (doubleValue == null) {
setState(() {
errorMessage = "Invalid number";
hasError = true;
});
return;
}
final min = widget.sliderRange.$1;
final max = widget.sliderRange.$2;
if (doubleValue < min) {
setState(() {
errorMessage = "Value must be at least $min";
hasError = true;
});
} else if (doubleValue > max) {
setState(() {
errorMessage = "Value must be at most $max";
hasError = true;
});
} else {
int decimalPlaces = getDecimalPlaces(widget.stepIncreaseAmount);
int factor = pow(10, decimalPlaces).toInt();
int scaledStep = (widget.stepIncreaseAmount * factor).round();
int scaledValue = (doubleValue * factor).round();
if (scaledValue % scaledStep != 0) {
setState(() {
errorMessage = "must be a multiple of ${widget.stepIncreaseAmount}";
hasError = true;
});
} else {
setState(() {
errorMessage = null;
hasError = false;
});
}
}
}
@override
void didUpdateWidget(CustomRoutinesTextbox oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.initialValue != oldWidget.initialValue) {
if (widget.initialValue != null &&
widget.initialValue is num &&
(widget.initialValue as num) == 0) {
int decimalPlaces = getDecimalPlaces(widget.stepIncreaseAmount);
_controller.text = 0.0.toStringAsFixed(decimalPlaces);
}
}
}
void _correctAndUpdateValue(String value) {
final doubleValue = double.tryParse(value) ?? 0.0;
int decimalPlaces = getDecimalPlaces(widget.stepIncreaseAmount);
double rounded = (doubleValue / widget.stepIncreaseAmount).round() *
widget.stepIncreaseAmount;
rounded = rounded.clamp(widget.sliderRange.$1, widget.sliderRange.$2);
rounded = double.parse(rounded.toStringAsFixed(decimalPlaces));
setState(() {
hasError = false;
errorMessage = null;
});
_controller.text = rounded.toStringAsFixed(decimalPlaces);
_controller.selection = TextSelection.fromPosition(
TextPosition(offset: _controller.text.length),
);
widget.onTextChanged(rounded);
}
@override
Widget build(BuildContext context) {
int decimalPlaces = getDecimalPlaces(widget.stepIncreaseAmount);
List<TextInputFormatter> formatters = [];
if (decimalPlaces == 0) {
formatters.add(FilteringTextInputFormatter.digitsOnly);
} else {
formatters.add(FilteringTextInputFormatter.allow(
RegExp(r'^\d*\.?\d{0,' + decimalPlaces.toString() + r'}$'),
));
}
formatters.add(RangeInputFormatter(
min: widget.sliderRange.$1,
max: widget.sliderRange.$2,
));
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (widget.dialogType == 'IF')
ConditionToggle(
currentCondition: widget.currentCondition,
onChanged: widget.onConditionChanged,
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 35, vertical: 2),
child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text(
'Step: ${widget.stepIncreaseAmount}',
style: context.textTheme.bodySmall?.copyWith(
color: ColorsManager.grayColor,
fontSize: 10,
fontWeight: FontWeight.w400,
),
),
],
),
),
Center(
child: Container(
width: 170,
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 8),
decoration: BoxDecoration(
color: const Color(0xFFF8F8F8),
borderRadius: BorderRadius.circular(20),
border: hasError
? Border.all(color: Colors.red, width: 1)
: Border.all(
color: ColorsManager.lightGrayBorderColor, width: 1),
boxShadow: [
BoxShadow(
color: ColorsManager.blackColor.withOpacity(0.05),
blurRadius: 8,
offset: const Offset(0, 4),
),
],
),
child: Row(
children: [
Expanded(
child: TextFormField(
controller: _controller,
style: context.textTheme.bodyLarge?.copyWith(
fontSize: 20,
fontWeight: FontWeight.bold,
color: ColorsManager.blackColor,
),
keyboardType: TextInputType.number,
inputFormatters: widget.withSpecialChar == true
? [FilteringTextInputFormatter.digitsOnly]
: null,
decoration: const InputDecoration(
border: InputBorder.none,
isDense: true,
contentPadding: EdgeInsets.zero,
),
onChanged: _validateInput,
onFieldSubmitted: _correctAndUpdateValue,
onTapOutside: (_) =>
_correctAndUpdateValue(_controller.text),
),
),
const SizedBox(width: 12),
Text(
widget.unit,
style: context.textTheme.bodyMedium?.copyWith(
fontSize: 20,
fontWeight: FontWeight.bold,
color: ColorsManager.vividBlue,
),
),
],
),
),
),
if (errorMessage != null)
Padding(
padding: const EdgeInsets.only(top: 2.0),
child: Text(
errorMessage!,
style: context.textTheme.bodySmall?.copyWith(
color: Colors.red,
fontSize: 10,
),
),
),
const SizedBox(height: 16),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 32),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Min. ${widget.sliderRange.$1.toInt()}${widget.unit}',
style: context.textTheme.bodySmall?.copyWith(
color: ColorsManager.grayColor,
fontSize: 10,
fontWeight: FontWeight.w400,
),
),
Text(
'Max. ${widget.sliderRange.$2.toInt()}${widget.unit}',
style: context.textTheme.bodySmall?.copyWith(
color: ColorsManager.grayColor,
fontSize: 10,
fontWeight: FontWeight.w400,
),
),
],
),
),
const SizedBox(height: 16),
],
);
}
}
@@ -7,6 +7,7 @@ import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart';
import 'package:syncrow_web/pages/routines/models/ac/ac_function.dart'; import 'package:syncrow_web/pages/routines/models/ac/ac_function.dart';
import 'package:syncrow_web/pages/routines/models/ac/ac_operational_value.dart'; import 'package:syncrow_web/pages/routines/models/ac/ac_operational_value.dart';
import 'package:syncrow_web/pages/routines/models/device_functions.dart'; import 'package:syncrow_web/pages/routines/models/device_functions.dart';
import 'package:syncrow_web/pages/routines/widgets/custom_routines_textbox.dart';
import 'package:syncrow_web/pages/routines/widgets/dialog_footer.dart'; import 'package:syncrow_web/pages/routines/widgets/dialog_footer.dart';
import 'package:syncrow_web/pages/routines/widgets/dialog_header.dart'; import 'package:syncrow_web/pages/routines/widgets/dialog_header.dart';
import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/helpers/routine_tap_function_helper.dart'; import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/helpers/routine_tap_function_helper.dart';
@@ -76,24 +77,20 @@ class ACHelper {
context: context, context: context,
acFunctions: acFunctions, acFunctions: acFunctions,
device: device, device: device,
onFunctionSelected: (functionCode, operationName) { onFunctionSelected:
(functionCode, operationName) {
RoutineTapFunctionHelper.onTapFunction( RoutineTapFunctionHelper.onTapFunction(
context, context,
functionCode: functionCode, functionCode: functionCode,
functionOperationName: operationName, functionOperationName: operationName,
functionValueDescription: functionValueDescription:
selectedFunctionData.valueDescription, selectedFunctionData.valueDescription,
deviceUuid: device?.uuid, deviceUuid: device?.uuid,
codesToAddIntoFunctionsWithDefaultValue: [ codesToAddIntoFunctionsWithDefaultValue: [
'temp_set', 'temp_set',
'temp_current', 'temp_current',
], ],
defaultValue: functionCode == 'temp_set' defaultValue: 0);
? 200
: functionCode == 'temp_current'
? -100
: 0,
);
}, },
), ),
), ),
@@ -206,27 +203,61 @@ class ACHelper {
required String operationName, required String operationName,
bool? removeComparators, bool? removeComparators,
}) { }) {
final initialVal = selectedFunction == 'temp_set' ? 200 : -100; final selectedFn =
acFunctions.firstWhere((f) => f.code == selectedFunction);
if (selectedFunction == 'temp_set' || selectedFunction == 'temp_current') { if (selectedFunction == 'temp_set' || selectedFunction == 'temp_current') {
final initialValue = selectedFunctionData?.value ?? initialVal; // Convert stored integer value to display value
return _buildTemperatureSelector( final displayValue =
context: context, (selectedFunctionData?.value ?? selectedFn.min ?? 0) / 10;
initialValue: initialValue, final minValue = selectedFn.min! / 10;
selectCode: selectedFunction, final maxValue = selectedFn.max! / 10;
return CustomRoutinesTextbox(
withSpecialChar: true,
dividendOfRange: maxValue,
currentCondition: selectedFunctionData?.condition, currentCondition: selectedFunctionData?.condition,
device: device, dialogType: selectedFn.type,
operationName: operationName, sliderRange: (minValue, maxValue),
selectedFunctionData: selectedFunctionData, displayedValue: displayValue.toStringAsFixed(1),
removeComparators: removeComparators, initialValue: displayValue.toDouble(),
unit: selectedFn.unit!,
onConditionChanged: (condition) => context.read<FunctionBloc>().add(
AddFunction(
functionData: DeviceFunctionData(
entityId: device?.uuid ?? '',
functionCode: selectedFunction,
operationName: selectedFn.operationName,
condition: condition,
value: 0,
step: selectedFn.step,
unit: selectedFn.unit,
max: selectedFn.max,
min: selectedFn.min,
),
),
),
onTextChanged: (value) => context.read<FunctionBloc>().add(
AddFunction(
functionData: DeviceFunctionData(
entityId: device?.uuid ?? '',
functionCode: selectedFunction,
operationName: selectedFn.operationName,
value: (value * 10).round(), // Store as integer
condition: selectedFunctionData?.condition,
step: selectedFn.step,
unit: selectedFn.unit,
max: selectedFn.max,
min: selectedFn.min,
),
),
),
stepIncreaseAmount: selectedFn.step! / 10, // Convert step for display
); );
} }
final selectedFn = acFunctions.firstWhere((f) => f.code == selectedFunction);
final values = selectedFn.getOperationalValues();
return _buildOperationalValuesList( return _buildOperationalValuesList(
context: context, context: context,
values: values, values: selectedFn.getOperationalValues(),
selectedValue: selectedFunctionData?.value, selectedValue: selectedFunctionData?.value,
device: device, device: device,
operationName: operationName, operationName: operationName,
@@ -235,150 +266,151 @@ class ACHelper {
); );
} }
/// Build temperature selector for AC functions dialog // /// Build temperature selector for AC functions dialog
static Widget _buildTemperatureSelector({ // static Widget _buildTemperatureSelector({
required BuildContext context, // required BuildContext context,
required dynamic initialValue, // required dynamic initialValue,
required String? currentCondition, // required String? currentCondition,
required String selectCode, // required String selectCode,
AllDevicesModel? device, // AllDevicesModel? device,
required String operationName, // required String operationName,
DeviceFunctionData? selectedFunctionData, // DeviceFunctionData? selectedFunctionData,
bool? removeComparators, // bool? removeComparators,
}) { // }) {
return Column( // return Column(
mainAxisAlignment: MainAxisAlignment.center, // mainAxisAlignment: MainAxisAlignment.center,
children: [ // children: [
if (removeComparators != true) // if (removeComparators != true)
_buildConditionToggle( // _buildConditionToggle(
context, // context,
currentCondition, // currentCondition,
selectCode, // selectCode,
device, // device,
operationName, // operationName,
selectedFunctionData, // selectedFunctionData,
), // ),
const SizedBox(height: 20), // const SizedBox(height: 20),
_buildTemperatureDisplay( // _buildTemperatureDisplay(
context, // context,
initialValue, // initialValue,
device, // device,
operationName, // operationName,
selectedFunctionData, // selectedFunctionData,
selectCode, // selectCode,
), // ),
const SizedBox(height: 20), // const SizedBox(height: 20),
_buildTemperatureSlider( // _buildTemperatureSlider(
context, // context,
initialValue, // initialValue,
device, // device,
operationName, // operationName,
selectedFunctionData, // selectedFunctionData,
selectCode, // selectCode,
), // ),
], // ],
); // );
} // }
/// Build condition toggle for AC functions dialog // /// Build condition toggle for AC functions dialog
static Widget _buildConditionToggle( // static Widget _buildConditionToggle(
BuildContext context, // BuildContext context,
String? currentCondition, // String? currentCondition,
String selectCode, // String selectCode,
AllDevicesModel? device, // AllDevicesModel? device,
String operationName, // String operationName,
DeviceFunctionData? selectedFunctionData, // DeviceFunctionData? selectedFunctionData,
// Function(String) onConditionChanged, // // Function(String) onConditionChanged,
) { // ) {
final conditions = ["<", "==", ">"]; // final conditions = ["<", "==", ">"];
return ToggleButtons( // return ToggleButtons(
onPressed: (int index) { // onPressed: (int index) {
context.read<FunctionBloc>().add( // context.read<FunctionBloc>().add(
AddFunction( // AddFunction(
functionData: DeviceFunctionData( // functionData: DeviceFunctionData(
entityId: device?.uuid ?? '', // entityId: device?.uuid ?? '',
functionCode: selectCode, // functionCode: selectCode,
operationName: operationName, // operationName: operationName,
condition: conditions[index], // condition: conditions[index],
value: selectedFunctionData?.value ?? selectCode == 'temp_set' // value: selectedFunctionData?.value ?? selectCode == 'temp_set'
? 200 // ? 200
: -100, // : -100,
valueDescription: selectedFunctionData?.valueDescription, // valueDescription: selectedFunctionData?.valueDescription,
), // ),
), // ),
); // );
}, // },
borderRadius: const BorderRadius.all(Radius.circular(8)), // borderRadius: const BorderRadius.all(Radius.circular(8)),
selectedBorderColor: ColorsManager.primaryColorWithOpacity, // selectedBorderColor: ColorsManager.primaryColorWithOpacity,
selectedColor: Colors.white, // selectedColor: Colors.white,
fillColor: ColorsManager.primaryColorWithOpacity, // fillColor: ColorsManager.primaryColorWithOpacity,
color: ColorsManager.primaryColorWithOpacity, // color: ColorsManager.primaryColorWithOpacity,
constraints: const BoxConstraints( // constraints: const BoxConstraints(
minHeight: 40.0, // minHeight: 40.0,
minWidth: 40.0, // minWidth: 40.0,
), // ),
isSelected: conditions.map((c) => c == (currentCondition ?? "==")).toList(), // isSelected:
children: conditions.map((c) => Text(c)).toList(), // conditions.map((c) => c == (currentCondition ?? "==")).toList(),
); // children: conditions.map((c) => Text(c)).toList(),
} // );
// }
/// Build temperature display for AC functions dialog // /// Build temperature display for AC functions dialog
static Widget _buildTemperatureDisplay( // static Widget _buildTemperatureDisplay(
BuildContext context, // BuildContext context,
dynamic initialValue, // dynamic initialValue,
AllDevicesModel? device, // AllDevicesModel? device,
String operationName, // String operationName,
DeviceFunctionData? selectedFunctionData, // DeviceFunctionData? selectedFunctionData,
String selectCode, // String selectCode,
) { // ) {
final initialVal = selectCode == 'temp_set' ? 200 : -100; // final initialVal = selectCode == 'temp_set' ? 200 : -100;
return Container( // return Container(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), // padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
decoration: BoxDecoration( // decoration: BoxDecoration(
color: ColorsManager.primaryColorWithOpacity.withOpacity(0.1), // color: ColorsManager.primaryColorWithOpacity.withOpacity(0.1),
borderRadius: BorderRadius.circular(10), // borderRadius: BorderRadius.circular(10),
), // ),
child: Text( // child: Text(
'${(initialValue ?? initialVal) / 10}°C', // '${(initialValue ?? initialVal) / 10}°C',
style: context.textTheme.headlineMedium!.copyWith( // style: context.textTheme.headlineMedium!.copyWith(
color: ColorsManager.primaryColorWithOpacity, // color: ColorsManager.primaryColorWithOpacity,
), // ),
), // ),
); // );
} // }
static Widget _buildTemperatureSlider( // static Widget _buildTemperatureSlider(
BuildContext context, // BuildContext context,
dynamic initialValue, // dynamic initialValue,
AllDevicesModel? device, // AllDevicesModel? device,
String operationName, // String operationName,
DeviceFunctionData? selectedFunctionData, // DeviceFunctionData? selectedFunctionData,
String selectCode, // String selectCode,
) { // ) {
return Slider( // return Slider(
value: initialValue is int ? initialValue.toDouble() : 200.0, // value: initialValue is int ? initialValue.toDouble() : 200.0,
min: selectCode == 'temp_current' ? -100 : 200, // min: selectCode == 'temp_current' ? -100 : 200,
max: selectCode == 'temp_current' ? 900 : 300, // max: selectCode == 'temp_current' ? 900 : 300,
divisions: 10, // divisions: 10,
label: '${((initialValue ?? 160) / 10).toInt()}°C', // label: '${((initialValue ?? 160) / 10).toInt()}°C',
onChanged: (value) { // onChanged: (value) {
context.read<FunctionBloc>().add( // context.read<FunctionBloc>().add(
AddFunction( // AddFunction(
functionData: DeviceFunctionData( // functionData: DeviceFunctionData(
entityId: device?.uuid ?? '', // entityId: device?.uuid ?? '',
functionCode: selectCode, // functionCode: selectCode,
operationName: operationName, // operationName: operationName,
value: value, // value: value,
condition: selectedFunctionData?.condition, // condition: selectedFunctionData?.condition,
valueDescription: selectedFunctionData?.valueDescription, // valueDescription: selectedFunctionData?.valueDescription,
), // ),
), // ),
); // );
}, // },
); // );
} // }
static Widget _buildOperationalValuesList({ static Widget _buildOperationalValuesList({
required BuildContext context, required BuildContext context,
@@ -414,7 +446,9 @@ class ACHelper {
style: context.textTheme.bodyMedium, style: context.textTheme.bodyMedium,
), ),
trailing: Icon( trailing: Icon(
isSelected ? Icons.radio_button_checked : Icons.radio_button_unchecked, isSelected
? Icons.radio_button_checked
: Icons.radio_button_unchecked,
size: 24, size: 24,
color: isSelected color: isSelected
? ColorsManager.primaryColorWithOpacity ? ColorsManager.primaryColorWithOpacity
@@ -430,7 +464,8 @@ class ACHelper {
operationName: operationName, operationName: operationName,
value: value.value, value: value.value,
condition: selectedFunctionData?.condition, condition: selectedFunctionData?.condition,
valueDescription: selectedFunctionData?.valueDescription, valueDescription:
selectedFunctionData?.valueDescription,
), ),
), ),
); );
@@ -41,7 +41,8 @@ class _CeilingSensorDialogState extends State<CeilingSensorDialog> {
void initState() { void initState() {
super.initState(); super.initState();
_cpsFunctions = widget.functions.whereType<CpsFunctions>().where((function) { _cpsFunctions =
widget.functions.whereType<CpsFunctions>().where((function) {
if (widget.dialogType == 'THEN') { if (widget.dialogType == 'THEN') {
return function.type == 'THEN' || function.type == 'BOTH'; return function.type == 'THEN' || function.type == 'BOTH';
} }
@@ -149,6 +150,7 @@ class _CeilingSensorDialogState extends State<CeilingSensorDialog> {
device: widget.device, device: widget.device,
) )
: CpsDialogSliderSelector( : CpsDialogSliderSelector(
step: selectedCpsFunctions.step!,
operations: operations, operations: operations,
selectedFunction: selectedFunction ?? '', selectedFunction: selectedFunction ?? '',
selectedFunctionData: selectedFunctionData, selectedFunctionData: selectedFunctionData,
@@ -4,6 +4,7 @@ import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_mo
import 'package:syncrow_web/pages/routines/bloc/functions_bloc/functions_bloc_bloc.dart'; import 'package:syncrow_web/pages/routines/bloc/functions_bloc/functions_bloc_bloc.dart';
import 'package:syncrow_web/pages/routines/models/ceiling_presence_sensor_functions.dart'; import 'package:syncrow_web/pages/routines/models/ceiling_presence_sensor_functions.dart';
import 'package:syncrow_web/pages/routines/models/device_functions.dart'; import 'package:syncrow_web/pages/routines/models/device_functions.dart';
import 'package:syncrow_web/pages/routines/widgets/custom_routines_textbox.dart';
import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/ceiling_sensor/cps_slider_helpers.dart'; import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/ceiling_sensor/cps_slider_helpers.dart';
import 'package:syncrow_web/pages/routines/widgets/slider_value_selector.dart'; import 'package:syncrow_web/pages/routines/widgets/slider_value_selector.dart';
@@ -16,6 +17,7 @@ class CpsDialogSliderSelector extends StatelessWidget {
required this.device, required this.device,
required this.operationName, required this.operationName,
required this.dialogType, required this.dialogType,
required this.step,
super.key, super.key,
}); });
@@ -26,13 +28,16 @@ class CpsDialogSliderSelector extends StatelessWidget {
final AllDevicesModel? device; final AllDevicesModel? device;
final String operationName; final String operationName;
final String dialogType; final String dialogType;
final double step;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return SliderValueSelector( return CustomRoutinesTextbox(
withSpecialChar: false,
currentCondition: selectedFunctionData.condition, currentCondition: selectedFunctionData.condition,
dialogType: dialogType, dialogType: dialogType,
sliderRange: CpsSliderHelpers.sliderRange(selectedFunctionData.functionCode), sliderRange:
CpsSliderHelpers.sliderRange(selectedFunctionData.functionCode),
displayedValue: CpsSliderHelpers.displayText( displayedValue: CpsSliderHelpers.displayText(
value: selectedFunctionData.value, value: selectedFunctionData.value,
functionCode: selectedFunctionData.functionCode, functionCode: selectedFunctionData.functionCode,
@@ -50,7 +55,7 @@ class CpsDialogSliderSelector extends StatelessWidget {
), ),
), ),
), ),
onSliderChanged: (value) => context.read<FunctionBloc>().add( onTextChanged: (value) => context.read<FunctionBloc>().add(
AddFunction( AddFunction(
functionData: DeviceFunctionData( functionData: DeviceFunctionData(
entityId: device?.uuid ?? '', entityId: device?.uuid ?? '',
@@ -64,6 +69,7 @@ class CpsDialogSliderSelector extends StatelessWidget {
dividendOfRange: CpsSliderHelpers.dividendOfRange( dividendOfRange: CpsSliderHelpers.dividendOfRange(
selectedFunctionData.functionCode, selectedFunctionData.functionCode,
), ),
stepIncreaseAmount: step,
); );
} }
} }
@@ -34,30 +34,33 @@ class CpsFunctionsList extends StatelessWidget {
itemBuilder: (context, index) { itemBuilder: (context, index) {
final function = cpsFunctions[index]; final function = cpsFunctions[index];
return RoutineDialogFunctionListTile( return RoutineDialogFunctionListTile(
iconPath: function.icon, iconPath: function.icon,
operationName: function.operationName, operationName: function.operationName,
onTap: () => RoutineTapFunctionHelper.onTapFunction( onTap: () {
context, RoutineTapFunctionHelper.onTapFunction(
functionCode: function.code, context,
functionOperationName: function.operationName, step: function.step,
functionValueDescription: selectedFunctionData?.valueDescription, functionCode: function.code,
deviceUuid: device?.uuid, functionOperationName: function.operationName,
codesToAddIntoFunctionsWithDefaultValue: [ functionValueDescription:
'static_max_dis', selectedFunctionData?.valueDescription,
'presence_reference', deviceUuid: device?.uuid,
'moving_reference', codesToAddIntoFunctionsWithDefaultValue: [
'perceptual_boundary', 'static_max_dis',
'moving_boundary', 'presence_reference',
'moving_rigger_time', 'moving_reference',
'moving_static_time', 'perceptual_boundary',
'none_body_time', 'moving_boundary',
'moving_max_dis', 'moving_rigger_time',
'moving_range', 'moving_static_time',
'presence_range', 'none_body_time',
if (dialogType == "IF") 'sensitivity', 'moving_max_dis',
], 'moving_range',
), 'presence_range',
); if (dialogType == "IF") 'sensitivity',
],
);
});
}, },
), ),
); );
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
import 'package:syncrow_web/pages/routines/models/flush/flush_operational_value.dart'; import 'package:syncrow_web/pages/routines/models/flush/flush_operational_value.dart';
@@ -21,22 +22,20 @@ class FlushOperationalValuesList extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ListView.builder( return ListView.builder(
padding: const EdgeInsets.all(20), padding: const EdgeInsets.all(20),
itemCount: values.length, itemCount: values.length,
itemBuilder: (context, index) => itemBuilder: (context, index) => _buildValueItem(context, values[index]),
_buildValueItem(context, values[index]), );
);
} }
Widget _buildValueItem(BuildContext context, FlushOperationalValue value) { Widget _buildValueItem(BuildContext context, FlushOperationalValue value) {
return Padding( return Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
SvgPicture.asset(value.icon, width: 25, height: 25),
Expanded(child: _buildValueDescription(value)), Expanded(child: _buildValueDescription(value)),
_buildValueRadio(context, value), _buildValueRadio(context, value),
], ],
@@ -44,9 +43,6 @@ class FlushOperationalValuesList extends StatelessWidget {
); );
} }
Widget _buildValueDescription(FlushOperationalValue value) { Widget _buildValueDescription(FlushOperationalValue value) {
return Padding( return Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0), padding: const EdgeInsets.symmetric(horizontal: 8.0),
@@ -60,6 +56,4 @@ class FlushOperationalValuesList extends StatelessWidget {
groupValue: selectedValue, groupValue: selectedValue,
onChanged: (_) => onSelect(value)); onChanged: (_) => onSelect(value));
} }
} }
@@ -5,6 +5,7 @@ import 'package:syncrow_web/pages/device_managment/flush_mounted_presence_sensor
import 'package:syncrow_web/pages/routines/bloc/functions_bloc/functions_bloc_bloc.dart'; import 'package:syncrow_web/pages/routines/bloc/functions_bloc/functions_bloc_bloc.dart';
import 'package:syncrow_web/pages/routines/models/device_functions.dart'; import 'package:syncrow_web/pages/routines/models/device_functions.dart';
import 'package:syncrow_web/pages/routines/models/flush/flush_functions.dart'; import 'package:syncrow_web/pages/routines/models/flush/flush_functions.dart';
import 'package:syncrow_web/pages/routines/widgets/custom_routines_textbox.dart';
import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/flush_presence_sensor/flush_operational_values_list.dart'; import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/flush_presence_sensor/flush_operational_values_list.dart';
import 'package:syncrow_web/pages/routines/widgets/slider_value_selector.dart'; import 'package:syncrow_web/pages/routines/widgets/slider_value_selector.dart';
@@ -66,7 +67,8 @@ class FlushValueSelectorWidget extends StatelessWidget {
if (isDistanceDetection) { if (isDistanceDetection) {
initialValue = initialValue / 100; initialValue = initialValue / 100;
} }
return SliderValueSelector( return CustomRoutinesTextbox(
withSpecialChar: true,
currentCondition: functionData.condition, currentCondition: functionData.condition,
dialogType: dialogType, dialogType: dialogType,
sliderRange: sliderRange, sliderRange: sliderRange,
@@ -83,7 +85,7 @@ class FlushValueSelectorWidget extends StatelessWidget {
), ),
), ),
), ),
onSliderChanged: (value) { onTextChanged: (value) {
final roundedValue = _roundToStep(value, stepSize); final roundedValue = _roundToStep(value, stepSize);
final finalValue = final finalValue =
isDistanceDetection ? (roundedValue * 100).toInt() : roundedValue; isDistanceDetection ? (roundedValue * 100).toInt() : roundedValue;
@@ -102,6 +104,7 @@ class FlushValueSelectorWidget extends StatelessWidget {
}, },
unit: _unit, unit: _unit,
dividendOfRange: stepSize, dividendOfRange: stepSize,
stepIncreaseAmount: stepSize,
); );
} }
@@ -8,6 +8,7 @@ abstract final class RoutineTapFunctionHelper {
static void onTapFunction( static void onTapFunction(
BuildContext context, { BuildContext context, {
double? step,
required String functionCode, required String functionCode,
required String functionOperationName, required String functionOperationName,
required String? functionValueDescription, required String? functionValueDescription,
@@ -4,11 +4,11 @@ import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
import 'package:syncrow_web/pages/routines/bloc/functions_bloc/functions_bloc_bloc.dart'; import 'package:syncrow_web/pages/routines/bloc/functions_bloc/functions_bloc_bloc.dart';
import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart'; import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart';
import 'package:syncrow_web/pages/routines/helper/duration_format_helper.dart';
import 'package:syncrow_web/pages/routines/models/device_functions.dart'; import 'package:syncrow_web/pages/routines/models/device_functions.dart';
import 'package:syncrow_web/pages/routines/models/gang_switches/base_switch_function.dart'; import 'package:syncrow_web/pages/routines/models/gang_switches/base_switch_function.dart';
import 'package:syncrow_web/pages/routines/models/gang_switches/one_gang_switch/one_gang_switch.dart'; import 'package:syncrow_web/pages/routines/models/gang_switches/one_gang_switch/one_gang_switch.dart';
import 'package:syncrow_web/pages/routines/models/gang_switches/switch_operational_value.dart'; import 'package:syncrow_web/pages/routines/models/gang_switches/switch_operational_value.dart';
import 'package:syncrow_web/pages/routines/widgets/custom_routines_textbox.dart';
import 'package:syncrow_web/pages/routines/widgets/dialog_footer.dart'; import 'package:syncrow_web/pages/routines/widgets/dialog_footer.dart';
import 'package:syncrow_web/pages/routines/widgets/dialog_header.dart'; import 'package:syncrow_web/pages/routines/widgets/dialog_header.dart';
import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/helpers/routine_tap_function_helper.dart'; import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/helpers/routine_tap_function_helper.dart';
@@ -87,14 +87,15 @@ class OneGangSwitchHelper {
size: 16, size: 16,
color: ColorsManager.textGray, color: ColorsManager.textGray,
), ),
onTap: () => onTap: () => RoutineTapFunctionHelper
RoutineTapFunctionHelper.onTapFunction( .onTapFunction(
context, context,
functionCode: function.code, functionCode: function.code,
functionOperationName: functionOperationName:
function.operationName, function.operationName,
functionValueDescription: functionValueDescription:
selectedFunctionData.valueDescription, selectedFunctionData
.valueDescription,
deviceUuid: device?.uuid, deviceUuid: device?.uuid,
codesToAddIntoFunctionsWithDefaultValue: [ codesToAddIntoFunctionsWithDefaultValue: [
'countdown_1', 'countdown_1',
@@ -108,14 +109,16 @@ class OneGangSwitchHelper {
if (selectedFunction != null) if (selectedFunction != null)
Expanded( Expanded(
child: _buildValueSelector( child: _buildValueSelector(
context: context, context: context,
selectedFunction: selectedFunction, selectedFunction: selectedFunction,
selectedFunctionData: selectedFunctionData, selectedFunctionData:
acFunctions: oneGangFunctions, selectedFunctionData,
device: device, acFunctions: oneGangFunctions,
operationName: selectedOperationName ?? '', device: device,
removeComparetors: removeComparetors, operationName:
), selectedOperationName ?? '',
removeComparetors: removeComparetors,
dialogType: dialogType),
), ),
], ],
), ),
@@ -172,6 +175,7 @@ class OneGangSwitchHelper {
AllDevicesModel? device, AllDevicesModel? device,
required String operationName, required String operationName,
required bool removeComparetors, required bool removeComparetors,
required String dialogType,
}) { }) {
if (selectedFunction == 'countdown_1') { if (selectedFunction == 'countdown_1') {
final initialValue = selectedFunctionData?.value ?? 0; final initialValue = selectedFunctionData?.value ?? 0;
@@ -184,6 +188,7 @@ class OneGangSwitchHelper {
operationName: operationName, operationName: operationName,
selectedFunctionData: selectedFunctionData, selectedFunctionData: selectedFunctionData,
removeComparetors: removeComparetors, removeComparetors: removeComparetors,
dialogType: dialogType,
); );
} }
final selectedFn = acFunctions.firstWhere( final selectedFn = acFunctions.firstWhere(
@@ -216,93 +221,18 @@ class OneGangSwitchHelper {
required String operationName, required String operationName,
DeviceFunctionData? selectedFunctionData, DeviceFunctionData? selectedFunctionData,
required bool removeComparetors, required bool removeComparetors,
String? dialogType,
}) { }) {
return Column( return Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
if (removeComparetors != true)
_buildConditionToggle(
context,
currentCondition,
selectCode,
device,
operationName,
selectedFunctionData,
),
const SizedBox(height: 20),
_buildCountDownDisplay(context, initialValue, device, operationName,
selectedFunctionData, selectCode),
const SizedBox(height: 20), const SizedBox(height: 20),
_buildCountDownSlider(context, initialValue, device, operationName, _buildCountDownSlider(context, initialValue, device, operationName,
selectedFunctionData, selectCode), selectedFunctionData, selectCode, dialogType!),
], ],
); );
} }
/// Build condition toggle for AC functions dialog
static Widget _buildConditionToggle(
BuildContext context,
String? currentCondition,
String selectCode,
AllDevicesModel? device,
String operationName,
DeviceFunctionData? selectedFunctionData,
// Function(String) onConditionChanged,
) {
final conditions = ["<", "==", ">"];
return ToggleButtons(
onPressed: (int index) {
context.read<FunctionBloc>().add(
AddFunction(
functionData: DeviceFunctionData(
entityId: device?.uuid ?? '',
functionCode: selectCode,
operationName: operationName,
condition: conditions[index],
value: selectedFunctionData?.value ?? 0,
valueDescription: selectedFunctionData?.valueDescription,
),
),
);
},
borderRadius: const BorderRadius.all(Radius.circular(8)),
selectedBorderColor: ColorsManager.primaryColorWithOpacity,
selectedColor: Colors.white,
fillColor: ColorsManager.primaryColorWithOpacity,
color: ColorsManager.primaryColorWithOpacity,
constraints: const BoxConstraints(
minHeight: 40.0,
minWidth: 40.0,
),
isSelected: conditions.map((c) => c == (currentCondition ?? "==")).toList(),
children: conditions.map((c) => Text(c)).toList(),
);
}
/// Build temperature display for AC functions dialog
static Widget _buildCountDownDisplay(
BuildContext context,
dynamic initialValue,
AllDevicesModel? device,
String operationName,
DeviceFunctionData? selectedFunctionData,
String selectCode) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
decoration: BoxDecoration(
color: ColorsManager.primaryColorWithOpacity.withOpacity(0.1),
borderRadius: BorderRadius.circular(10),
),
child: Text(
DurationFormatMixin.formatDuration(initialValue?.toInt() ?? 0),
style: context.textTheme.headlineMedium!.copyWith(
color: ColorsManager.primaryColorWithOpacity,
),
),
);
}
static Widget _buildCountDownSlider( static Widget _buildCountDownSlider(
BuildContext context, BuildContext context,
dynamic initialValue, dynamic initialValue,
@@ -310,38 +240,47 @@ class OneGangSwitchHelper {
String operationName, String operationName,
DeviceFunctionData? selectedFunctionData, DeviceFunctionData? selectedFunctionData,
String selectCode, String selectCode,
String dialogType,
) { ) {
const twelveHoursInSeconds = 43200.0; return CustomRoutinesTextbox(
final operationalValues = SwitchOperationalValue( withSpecialChar: false,
icon: '', currentCondition: selectedFunctionData?.condition,
description: "sec", dialogType: dialogType,
value: 0.0, sliderRange: (0, 43200),
minValue: 0, displayedValue: (initialValue ?? 0).toString(),
maxValue: twelveHoursInSeconds, initialValue: (initialValue ?? 0).toString(),
stepValue: 1, onConditionChanged: (condition) {
);
return Slider(
value: (initialValue ?? 0).toDouble(),
min: operationalValues.minValue?.toDouble() ?? 0.0,
max: operationalValues.maxValue?.toDouble() ?? 0.0,
divisions:
(((operationalValues.maxValue ?? 0) - (operationalValues.minValue ?? 0)) /
(operationalValues.stepValue ?? 1))
.round(),
onChanged: (value) {
context.read<FunctionBloc>().add( context.read<FunctionBloc>().add(
AddFunction( AddFunction(
functionData: DeviceFunctionData( functionData: DeviceFunctionData(
entityId: device?.uuid ?? '', entityId: device?.uuid ?? '',
functionCode: selectCode, functionCode: selectCode,
operationName: operationName, operationName: operationName,
value: value, condition: condition,
value: selectedFunctionData?.value ?? 0,
valueDescription: selectedFunctionData?.valueDescription,
),
),
);
},
onTextChanged: (value) {
final roundedValue = value.round();
context.read<FunctionBloc>().add(
AddFunction(
functionData: DeviceFunctionData(
entityId: device?.uuid ?? '',
functionCode: selectCode,
operationName: operationName,
value: roundedValue,
condition: selectedFunctionData?.condition, condition: selectedFunctionData?.condition,
valueDescription: selectedFunctionData?.valueDescription, valueDescription: selectedFunctionData?.valueDescription,
), ),
), ),
); );
}, },
unit: 'sec',
dividendOfRange: 1,
stepIncreaseAmount: 1,
); );
} }
@@ -377,7 +316,9 @@ class OneGangSwitchHelper {
style: context.textTheme.bodyMedium, style: context.textTheme.bodyMedium,
), ),
trailing: Icon( trailing: Icon(
isSelected ? Icons.radio_button_checked : Icons.radio_button_unchecked, isSelected
? Icons.radio_button_checked
: Icons.radio_button_unchecked,
size: 24, size: 24,
color: isSelected color: isSelected
? ColorsManager.primaryColorWithOpacity ? ColorsManager.primaryColorWithOpacity
@@ -393,7 +334,8 @@ class OneGangSwitchHelper {
operationName: operationName, operationName: operationName,
value: value.value, value: value.value,
condition: selectedFunctionData?.condition, condition: selectedFunctionData?.condition,
valueDescription: selectedFunctionData?.valueDescription, valueDescription:
selectedFunctionData?.valueDescription,
), ),
), ),
); );
@@ -4,10 +4,10 @@ import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
import 'package:syncrow_web/pages/routines/bloc/functions_bloc/functions_bloc_bloc.dart'; import 'package:syncrow_web/pages/routines/bloc/functions_bloc/functions_bloc_bloc.dart';
import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart'; import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart';
import 'package:syncrow_web/pages/routines/helper/duration_format_helper.dart';
import 'package:syncrow_web/pages/routines/models/device_functions.dart'; import 'package:syncrow_web/pages/routines/models/device_functions.dart';
import 'package:syncrow_web/pages/routines/models/gang_switches/base_switch_function.dart'; import 'package:syncrow_web/pages/routines/models/gang_switches/base_switch_function.dart';
import 'package:syncrow_web/pages/routines/models/gang_switches/switch_operational_value.dart'; import 'package:syncrow_web/pages/routines/models/gang_switches/switch_operational_value.dart';
import 'package:syncrow_web/pages/routines/widgets/custom_routines_textbox.dart';
import 'package:syncrow_web/pages/routines/widgets/dialog_footer.dart'; import 'package:syncrow_web/pages/routines/widgets/dialog_footer.dart';
import 'package:syncrow_web/pages/routines/widgets/dialog_header.dart'; import 'package:syncrow_web/pages/routines/widgets/dialog_header.dart';
import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/helpers/routine_tap_function_helper.dart'; import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/helpers/routine_tap_function_helper.dart';
@@ -86,20 +86,21 @@ class ThreeGangSwitchHelper {
size: 16, size: 16,
color: ColorsManager.textGray, color: ColorsManager.textGray,
), ),
onTap: () => onTap: () => RoutineTapFunctionHelper
RoutineTapFunctionHelper.onTapFunction( .onTapFunction(
context, context,
functionCode: function.code, functionCode: function.code,
functionOperationName: functionOperationName:
function.operationName, function.operationName,
functionValueDescription: functionValueDescription:
selectedFunctionData.valueDescription, selectedFunctionData
.valueDescription,
deviceUuid: device?.uuid, deviceUuid: device?.uuid,
codesToAddIntoFunctionsWithDefaultValue: [ codesToAddIntoFunctionsWithDefaultValue:
'countdown_1', function.code
'countdown_2', .startsWith('countdown')
'countdown_3', ? [function.code]
], : [],
), ),
); );
}, },
@@ -109,14 +110,16 @@ class ThreeGangSwitchHelper {
if (selectedFunction != null) if (selectedFunction != null)
Expanded( Expanded(
child: _buildValueSelector( child: _buildValueSelector(
context: context, context: context,
selectedFunction: selectedFunction, selectedFunction: selectedFunction,
selectedFunctionData: selectedFunctionData, selectedFunctionData:
switchFunctions: switchFunctions, selectedFunctionData,
device: device, switchFunctions: switchFunctions,
operationName: selectedOperationName ?? '', device: device,
removeComparetors: removeComparetors, operationName:
), selectedOperationName ?? '',
removeComparetors: removeComparetors,
dialogType: dialogType),
), ),
], ],
), ),
@@ -133,14 +136,6 @@ class ThreeGangSwitchHelper {
onConfirm: state.addedFunctions.isNotEmpty onConfirm: state.addedFunctions.isNotEmpty
? () { ? () {
/// add the functions to the routine bloc /// add the functions to the routine bloc
// for (var function in state.addedFunctions) {
// context.read<RoutineBloc>().add(
// AddFunctionToRoutine(
// function,
// uniqueCustomId,
// ),
// );
// }
context.read<RoutineBloc>().add( context.read<RoutineBloc>().add(
AddFunctionToRoutine( AddFunctionToRoutine(
state.addedFunctions, state.addedFunctions,
@@ -173,24 +168,26 @@ class ThreeGangSwitchHelper {
AllDevicesModel? device, AllDevicesModel? device,
required String operationName, required String operationName,
required bool removeComparetors, required bool removeComparetors,
required String dialogType,
}) { }) {
if (selectedFunction == 'countdown_1' || if (selectedFunction == 'countdown_1' ||
selectedFunction == 'countdown_2' || selectedFunction == 'countdown_2' ||
selectedFunction == 'countdown_3') { selectedFunction == 'countdown_3') {
final initialValue = selectedFunctionData?.value ?? 0; final initialValue = selectedFunctionData?.value ?? 0;
return _buildTemperatureSelector( return _buildTemperatureSelector(
context: context, context: context,
initialValue: initialValue, initialValue: initialValue,
selectCode: selectedFunction, selectCode: selectedFunction,
currentCondition: selectedFunctionData?.condition, currentCondition: selectedFunctionData?.condition,
device: device, device: device,
operationName: operationName, operationName: operationName,
selectedFunctionData: selectedFunctionData, selectedFunctionData: selectedFunctionData,
removeComparetors: removeComparetors, removeComparetors: removeComparetors,
); dialogType: dialogType);
} }
final selectedFn = switchFunctions.firstWhere((f) => f.code == selectedFunction); final selectedFn =
switchFunctions.firstWhere((f) => f.code == selectedFunction);
final values = selectedFn.getOperationalValues(); final values = selectedFn.getOperationalValues();
return _buildOperationalValuesList( return _buildOperationalValuesList(
@@ -213,93 +210,18 @@ class ThreeGangSwitchHelper {
required String operationName, required String operationName,
DeviceFunctionData? selectedFunctionData, DeviceFunctionData? selectedFunctionData,
bool? removeComparetors, bool? removeComparetors,
required String dialogType,
}) { }) {
return Column( return Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
if (removeComparetors != true)
_buildConditionToggle(
context,
currentCondition,
selectCode,
device,
operationName,
selectedFunctionData,
),
const SizedBox(height: 20),
_buildCountDownDisplay(context, initialValue, device, operationName,
selectedFunctionData, selectCode),
const SizedBox(height: 20), const SizedBox(height: 20),
_buildCountDownSlider(context, initialValue, device, operationName, _buildCountDownSlider(context, initialValue, device, operationName,
selectedFunctionData, selectCode), selectedFunctionData, selectCode, dialogType),
], ],
); );
} }
/// Build condition toggle for AC functions dialog
static Widget _buildConditionToggle(
BuildContext context,
String? currentCondition,
String selectCode,
AllDevicesModel? device,
String operationName,
DeviceFunctionData? selectedFunctionData,
// Function(String) onConditionChanged,
) {
final conditions = ["<", "==", ">"];
return ToggleButtons(
onPressed: (int index) {
context.read<FunctionBloc>().add(
AddFunction(
functionData: DeviceFunctionData(
entityId: device?.uuid ?? '',
functionCode: selectCode,
operationName: operationName,
condition: conditions[index],
value: selectedFunctionData?.value ?? 0,
valueDescription: selectedFunctionData?.valueDescription,
),
),
);
},
borderRadius: const BorderRadius.all(Radius.circular(8)),
selectedBorderColor: ColorsManager.primaryColorWithOpacity,
selectedColor: Colors.white,
fillColor: ColorsManager.primaryColorWithOpacity,
color: ColorsManager.primaryColorWithOpacity,
constraints: const BoxConstraints(
minHeight: 40.0,
minWidth: 40.0,
),
isSelected: conditions.map((c) => c == (currentCondition ?? "==")).toList(),
children: conditions.map((c) => Text(c)).toList(),
);
}
/// Build temperature display for AC functions dialog
static Widget _buildCountDownDisplay(
BuildContext context,
dynamic initialValue,
AllDevicesModel? device,
String operationName,
DeviceFunctionData? selectedFunctionData,
String selectCode) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
decoration: BoxDecoration(
color: ColorsManager.primaryColorWithOpacity.withOpacity(0.1),
borderRadius: BorderRadius.circular(10),
),
child: Text(
DurationFormatMixin.formatDuration(initialValue?.toInt() ?? 0),
style: context.textTheme.headlineMedium!.copyWith(
color: ColorsManager.primaryColorWithOpacity,
),
),
);
}
static Widget _buildCountDownSlider( static Widget _buildCountDownSlider(
BuildContext context, BuildContext context,
dynamic initialValue, dynamic initialValue,
@@ -307,38 +229,47 @@ class ThreeGangSwitchHelper {
String operationName, String operationName,
DeviceFunctionData? selectedFunctionData, DeviceFunctionData? selectedFunctionData,
String selectCode, String selectCode,
String dialogType,
) { ) {
const twelveHoursInSeconds = 43200.0; return CustomRoutinesTextbox(
final operationalValues = SwitchOperationalValue( withSpecialChar: true,
icon: '', currentCondition: selectedFunctionData?.condition,
description: "sec", dialogType: dialogType,
value: 0.0, sliderRange: (0, 43200),
minValue: 0, displayedValue: (initialValue ?? 0).toString(),
maxValue: twelveHoursInSeconds, initialValue: (initialValue ?? 0).toString(),
stepValue: 1, onConditionChanged: (condition) {
);
return Slider(
value: (initialValue ?? 0).toDouble(),
min: operationalValues.minValue?.toDouble() ?? 0.0,
max: operationalValues.maxValue?.toDouble() ?? 0.0,
divisions:
(((operationalValues.maxValue ?? 0) - (operationalValues.minValue ?? 0)) /
(operationalValues.stepValue ?? 1))
.round(),
onChanged: (value) {
context.read<FunctionBloc>().add( context.read<FunctionBloc>().add(
AddFunction( AddFunction(
functionData: DeviceFunctionData( functionData: DeviceFunctionData(
entityId: device?.uuid ?? '', entityId: device?.uuid ?? '',
functionCode: selectCode, functionCode: selectCode,
operationName: operationName, operationName: operationName,
value: value, condition: condition,
value: selectedFunctionData?.value ?? 0,
valueDescription: selectedFunctionData?.valueDescription,
),
),
);
},
onTextChanged: (value) {
final roundedValue = value.round();
context.read<FunctionBloc>().add(
AddFunction(
functionData: DeviceFunctionData(
entityId: device?.uuid ?? '',
functionCode: selectCode,
operationName: operationName,
value: roundedValue,
condition: selectedFunctionData?.condition, condition: selectedFunctionData?.condition,
valueDescription: selectedFunctionData?.valueDescription, valueDescription: selectedFunctionData?.valueDescription,
), ),
), ),
); );
}, },
unit: 'sec',
dividendOfRange: 1,
stepIncreaseAmount: 1,
); );
} }
@@ -374,7 +305,9 @@ class ThreeGangSwitchHelper {
style: context.textTheme.bodyMedium, style: context.textTheme.bodyMedium,
), ),
trailing: Icon( trailing: Icon(
isSelected ? Icons.radio_button_checked : Icons.radio_button_unchecked, isSelected
? Icons.radio_button_checked
: Icons.radio_button_unchecked,
size: 24, size: 24,
color: isSelected color: isSelected
? ColorsManager.primaryColorWithOpacity ? ColorsManager.primaryColorWithOpacity
@@ -390,7 +323,8 @@ class ThreeGangSwitchHelper {
operationName: operationName, operationName: operationName,
value: value.value, value: value.value,
condition: selectedFunctionData?.condition, condition: selectedFunctionData?.condition,
valueDescription: selectedFunctionData?.valueDescription, valueDescription:
selectedFunctionData?.valueDescription,
), ),
), ),
); );
@@ -8,6 +8,7 @@ import 'package:syncrow_web/pages/routines/helper/duration_format_helper.dart';
import 'package:syncrow_web/pages/routines/models/device_functions.dart'; import 'package:syncrow_web/pages/routines/models/device_functions.dart';
import 'package:syncrow_web/pages/routines/models/gang_switches/base_switch_function.dart'; import 'package:syncrow_web/pages/routines/models/gang_switches/base_switch_function.dart';
import 'package:syncrow_web/pages/routines/models/gang_switches/switch_operational_value.dart'; import 'package:syncrow_web/pages/routines/models/gang_switches/switch_operational_value.dart';
import 'package:syncrow_web/pages/routines/widgets/custom_routines_textbox.dart';
import 'package:syncrow_web/pages/routines/widgets/dialog_footer.dart'; import 'package:syncrow_web/pages/routines/widgets/dialog_footer.dart';
import 'package:syncrow_web/pages/routines/widgets/dialog_header.dart'; import 'package:syncrow_web/pages/routines/widgets/dialog_header.dart';
import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/helpers/routine_tap_function_helper.dart'; import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/helpers/routine_tap_function_helper.dart';
@@ -86,14 +87,15 @@ class TwoGangSwitchHelper {
size: 16, size: 16,
color: ColorsManager.textGray, color: ColorsManager.textGray,
), ),
onTap: () => onTap: () => RoutineTapFunctionHelper
RoutineTapFunctionHelper.onTapFunction( .onTapFunction(
context, context,
functionCode: function.code, functionCode: function.code,
functionOperationName: functionOperationName:
function.operationName, function.operationName,
functionValueDescription: functionValueDescription:
selectedFunctionData.valueDescription, selectedFunctionData
.valueDescription,
deviceUuid: device?.uuid, deviceUuid: device?.uuid,
codesToAddIntoFunctionsWithDefaultValue: [ codesToAddIntoFunctionsWithDefaultValue: [
'countdown_1', 'countdown_1',
@@ -115,6 +117,7 @@ class TwoGangSwitchHelper {
device: device, device: device,
operationName: selectedOperationName ?? '', operationName: selectedOperationName ?? '',
removeComparetors: removeComparetors, removeComparetors: removeComparetors,
dialogType: dialogType,
), ),
), ),
], ],
@@ -172,22 +175,25 @@ class TwoGangSwitchHelper {
AllDevicesModel? device, AllDevicesModel? device,
required String operationName, required String operationName,
required bool removeComparetors, required bool removeComparetors,
required String dialogType,
}) { }) {
if (selectedFunction == 'countdown_1' || selectedFunction == 'countdown_2') { if (selectedFunction == 'countdown_1' ||
selectedFunction == 'countdown_2') {
final initialValue = selectedFunctionData?.value ?? 0; final initialValue = selectedFunctionData?.value ?? 0;
return _buildTemperatureSelector( return _buildTemperatureSelector(
context: context, context: context,
initialValue: initialValue, initialValue: initialValue,
selectCode: selectedFunction, selectCode: selectedFunction,
currentCondition: selectedFunctionData?.condition, currentCondition: selectedFunctionData?.condition,
device: device, device: device,
operationName: operationName, operationName: operationName,
selectedFunctionData: selectedFunctionData, selectedFunctionData: selectedFunctionData,
removeComparetors: removeComparetors, removeComparetors: removeComparetors,
); dialogType: dialogType);
} }
final selectedFn = switchFunctions.firstWhere((f) => f.code == selectedFunction); final selectedFn =
switchFunctions.firstWhere((f) => f.code == selectedFunction);
final values = selectedFn.getOperationalValues(); final values = selectedFn.getOperationalValues();
return _buildOperationalValuesList( return _buildOperationalValuesList(
@@ -210,25 +216,13 @@ class TwoGangSwitchHelper {
required String operationName, required String operationName,
DeviceFunctionData? selectedFunctionData, DeviceFunctionData? selectedFunctionData,
bool? removeComparetors, bool? removeComparetors,
String? dialogType,
}) { }) {
return Column( return Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
if (removeComparetors != true)
_buildConditionToggle(
context,
currentCondition,
selectCode,
device,
operationName,
selectedFunctionData,
),
const SizedBox(height: 20),
_buildCountDownDisplay(context, initialValue, device, operationName,
selectedFunctionData, selectCode),
const SizedBox(height: 20),
_buildCountDownSlider(context, initialValue, device, operationName, _buildCountDownSlider(context, initialValue, device, operationName,
selectedFunctionData, selectCode), selectedFunctionData, selectCode, dialogType!),
], ],
); );
} }
@@ -269,7 +263,8 @@ class TwoGangSwitchHelper {
minHeight: 40.0, minHeight: 40.0,
minWidth: 40.0, minWidth: 40.0,
), ),
isSelected: conditions.map((c) => c == (currentCondition ?? "==")).toList(), isSelected:
conditions.map((c) => c == (currentCondition ?? "==")).toList(),
children: conditions.map((c) => Text(c)).toList(), children: conditions.map((c) => Text(c)).toList(),
); );
} }
@@ -304,38 +299,48 @@ class TwoGangSwitchHelper {
String operationName, String operationName,
DeviceFunctionData? selectedFunctionData, DeviceFunctionData? selectedFunctionData,
String selectCode, String selectCode,
String dialogType,
) { ) {
const twelveHoursInSeconds = 43200.0; return CustomRoutinesTextbox(
final operationalValues = SwitchOperationalValue( withSpecialChar: true,
icon: '', currentCondition: selectedFunctionData?.condition,
description: "sec", dialogType: dialogType,
value: 0.0, sliderRange: (0, 43200),
minValue: 0, displayedValue: (initialValue ?? 0).toString(),
maxValue: twelveHoursInSeconds, initialValue: (initialValue ?? 0).toString(),
stepValue: 1, onConditionChanged: (condition) {
);
return Slider(
value: (initialValue ?? 0).toDouble(),
min: operationalValues.minValue?.toDouble() ?? 0.0,
max: operationalValues.maxValue?.toDouble() ?? 0.0,
divisions:
(((operationalValues.maxValue ?? 0) - (operationalValues.minValue ?? 0)) /
(operationalValues.stepValue ?? 1))
.round(),
onChanged: (value) {
context.read<FunctionBloc>().add( context.read<FunctionBloc>().add(
AddFunction( AddFunction(
functionData: DeviceFunctionData( functionData: DeviceFunctionData(
entityId: device?.uuid ?? '', entityId: device?.uuid ?? '',
functionCode: selectCode, functionCode: selectCode,
operationName: operationName, operationName: operationName,
value: value, condition: condition,
value: selectedFunctionData?.value ?? 0,
valueDescription: selectedFunctionData?.valueDescription,
),
),
);
},
onTextChanged: (value) {
final roundedValue =
value.round(); // Round to nearest integer (stepSize 1)
context.read<FunctionBloc>().add(
AddFunction(
functionData: DeviceFunctionData(
entityId: device?.uuid ?? '',
functionCode: selectCode,
operationName: operationName,
value: roundedValue,
condition: selectedFunctionData?.condition, condition: selectedFunctionData?.condition,
valueDescription: selectedFunctionData?.valueDescription, valueDescription: selectedFunctionData?.valueDescription,
), ),
), ),
); );
}, },
unit: 'sec',
dividendOfRange: 1,
stepIncreaseAmount: 1,
); );
} }
@@ -371,7 +376,9 @@ class TwoGangSwitchHelper {
style: context.textTheme.bodyMedium, style: context.textTheme.bodyMedium,
), ),
trailing: Icon( trailing: Icon(
isSelected ? Icons.radio_button_checked : Icons.radio_button_unchecked, isSelected
? Icons.radio_button_checked
: Icons.radio_button_unchecked,
size: 24, size: 24,
color: isSelected color: isSelected
? ColorsManager.primaryColorWithOpacity ? ColorsManager.primaryColorWithOpacity
@@ -387,7 +394,8 @@ class TwoGangSwitchHelper {
operationName: operationName, operationName: operationName,
value: value.value, value: value.value,
condition: selectedFunctionData?.condition, condition: selectedFunctionData?.condition,
valueDescription: selectedFunctionData?.valueDescription, valueDescription:
selectedFunctionData?.valueDescription,
), ),
), ),
); );
@@ -4,8 +4,8 @@ import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_mo
import 'package:syncrow_web/pages/routines/bloc/functions_bloc/functions_bloc_bloc.dart'; import 'package:syncrow_web/pages/routines/bloc/functions_bloc/functions_bloc_bloc.dart';
import 'package:syncrow_web/pages/routines/models/device_functions.dart'; import 'package:syncrow_web/pages/routines/models/device_functions.dart';
import 'package:syncrow_web/pages/routines/models/wps/wps_functions.dart'; import 'package:syncrow_web/pages/routines/models/wps/wps_functions.dart';
import 'package:syncrow_web/pages/routines/widgets/custom_routines_textbox.dart';
import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/wall_sensor/wps_operational_values_list.dart'; import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/wall_sensor/wps_operational_values_list.dart';
import 'package:syncrow_web/pages/routines/widgets/slider_value_selector.dart';
class WpsValueSelectorWidget extends StatelessWidget { class WpsValueSelectorWidget extends StatelessWidget {
final String selectedFunction; final String selectedFunction;
@@ -27,11 +27,13 @@ class WpsValueSelectorWidget extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final selectedFn = wpsFunctions.firstWhere((f) => f.code == selectedFunction); final selectedFn =
wpsFunctions.firstWhere((f) => f.code == selectedFunction);
final values = selectedFn.getOperationalValues(); final values = selectedFn.getOperationalValues();
if (_isSliderFunction(selectedFunction)) { if (_isSliderFunction(selectedFunction)) {
return SliderValueSelector( return CustomRoutinesTextbox(
withSpecialChar: false,
currentCondition: functionData.condition, currentCondition: functionData.condition,
dialogType: dialogType, dialogType: dialogType,
sliderRange: sliderRange, sliderRange: sliderRange,
@@ -48,7 +50,7 @@ class WpsValueSelectorWidget extends StatelessWidget {
), ),
), ),
), ),
onSliderChanged: (value) => context.read<FunctionBloc>().add( onTextChanged: (value) => context.read<FunctionBloc>().add(
AddFunction( AddFunction(
functionData: DeviceFunctionData( functionData: DeviceFunctionData(
entityId: device?.uuid ?? '', entityId: device?.uuid ?? '',
@@ -61,6 +63,7 @@ class WpsValueSelectorWidget extends StatelessWidget {
), ),
unit: _unit, unit: _unit,
dividendOfRange: 1, dividendOfRange: 1,
stepIncreaseAmount: _steps,
); );
} }
@@ -99,4 +102,10 @@ class WpsValueSelectorWidget extends StatelessWidget {
'illuminance_value' => 'Lux', 'illuminance_value' => 'Lux',
_ => '', _ => '',
}; };
double get _steps => switch (functionData.functionCode) {
'presence_time' => 1,
'dis_current' => 1,
'illuminance_value' => 1,
_ => 1,
};
} }
@@ -176,6 +176,7 @@ class _WaterHeaterDialogRoutinesState extends State<WaterHeaterDialogRoutines> {
functionData: functionData, functionData: functionData,
whFunctions: _waterHeaterFunctions, whFunctions: _waterHeaterFunctions,
device: widget.device, device: widget.device,
dialogType: widget.dialogType,
), ),
); );
} }
@@ -2,25 +2,24 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
import 'package:syncrow_web/pages/routines/bloc/functions_bloc/functions_bloc_bloc.dart'; import 'package:syncrow_web/pages/routines/bloc/functions_bloc/functions_bloc_bloc.dart';
import 'package:syncrow_web/pages/routines/helper/duration_format_helper.dart';
import 'package:syncrow_web/pages/routines/models/device_functions.dart'; import 'package:syncrow_web/pages/routines/models/device_functions.dart';
import 'package:syncrow_web/pages/routines/models/gang_switches/switch_operational_value.dart';
import 'package:syncrow_web/pages/routines/models/water_heater/water_heater_functions.dart'; import 'package:syncrow_web/pages/routines/models/water_heater/water_heater_functions.dart';
import 'package:syncrow_web/pages/routines/widgets/custom_routines_textbox.dart';
import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/water_heater/water_heater_operational_values_list.dart'; import 'package:syncrow_web/pages/routines/widgets/routine_dialogs/water_heater/water_heater_operational_values_list.dart';
import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/extension/build_context_x.dart';
class WaterHeaterValueSelectorWidget extends StatelessWidget { class WaterHeaterValueSelectorWidget extends StatelessWidget {
final String selectedFunction; final String selectedFunction;
final DeviceFunctionData functionData; final DeviceFunctionData functionData;
final List<WaterHeaterFunctions> whFunctions; final List<WaterHeaterFunctions> whFunctions;
final AllDevicesModel? device; final AllDevicesModel? device;
final String dialogType;
const WaterHeaterValueSelectorWidget({ const WaterHeaterValueSelectorWidget({
required this.selectedFunction, required this.selectedFunction,
required this.functionData, required this.functionData,
required this.whFunctions, required this.whFunctions,
required this.device, required this.device,
required this.dialogType,
super.key, super.key,
}); });
@@ -39,22 +38,6 @@ class WaterHeaterValueSelectorWidget extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
_buildConditionToggle(
context,
functionData.condition,
selectedFunction,
device,
selectedFn.operationName,
functionData,
),
_buildCountDownDisplay(
context,
functionData.value,
device,
selectedFn.operationName,
functionData,
selectedFunction,
),
_buildCountDownSlider( _buildCountDownSlider(
context, context,
functionData.value, functionData.value,
@@ -62,6 +45,7 @@ class WaterHeaterValueSelectorWidget extends StatelessWidget {
selectedFn.operationName, selectedFn.operationName,
functionData, functionData,
selectedFunction, selectedFunction,
dialogType
), ),
const SizedBox(height: 10), const SizedBox(height: 10),
], ],
@@ -90,28 +74,6 @@ class WaterHeaterValueSelectorWidget extends StatelessWidget {
); );
} }
static Widget _buildCountDownDisplay(
BuildContext context,
dynamic initialValue,
AllDevicesModel? device,
String operationName,
DeviceFunctionData? selectedFunctionData,
String selectCode) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
decoration: BoxDecoration(
color: ColorsManager.primaryColorWithOpacity.withOpacity(0.1),
borderRadius: BorderRadius.circular(10),
),
child: Text(
DurationFormatMixin.formatDuration(initialValue?.toInt() ?? 0),
style: context.textTheme.headlineMedium!.copyWith(
color: ColorsManager.primaryColorWithOpacity,
),
),
);
}
static Widget _buildCountDownSlider( static Widget _buildCountDownSlider(
BuildContext context, BuildContext context,
dynamic initialValue, dynamic initialValue,
@@ -119,78 +81,47 @@ class WaterHeaterValueSelectorWidget extends StatelessWidget {
String operationName, String operationName,
DeviceFunctionData? selectedFunctionData, DeviceFunctionData? selectedFunctionData,
String selectCode, String selectCode,
String dialogType,
) { ) {
const twelveHoursInSeconds = 43200.0; return CustomRoutinesTextbox(
final operationalValues = SwitchOperationalValue( withSpecialChar: false,
icon: '', currentCondition: selectedFunctionData?.condition,
description: "sec", dialogType: dialogType,
value: 0.0, sliderRange: (0, 43200),
minValue: 0, displayedValue: (initialValue ?? 0).toString(),
maxValue: twelveHoursInSeconds, initialValue: (initialValue ?? 0).toString(),
stepValue: 1, onConditionChanged: (condition) {
);
return Slider(
value: (initialValue ?? 0).toDouble(),
min: operationalValues.minValue?.toDouble() ?? 0.0,
max: operationalValues.maxValue?.toDouble() ?? 0.0,
divisions: (((operationalValues.maxValue ?? 0) -
(operationalValues.minValue ?? 0)) /
(operationalValues.stepValue ?? 1))
.round(),
onChanged: (value) {
context.read<FunctionBloc>().add( context.read<FunctionBloc>().add(
AddFunction( AddFunction(
functionData: DeviceFunctionData( functionData: DeviceFunctionData(
entityId: device?.uuid ?? '', entityId: device?.uuid ?? '',
functionCode: selectCode, functionCode: selectCode,
operationName: operationName, operationName: operationName,
value: value, value: condition,
condition: condition,
valueDescription: selectedFunctionData?.valueDescription,
),
),
);
},
onTextChanged: (value) {
final roundedValue = value.round();
context.read<FunctionBloc>().add(
AddFunction(
functionData: DeviceFunctionData(
entityId: device?.uuid ?? '',
functionCode: selectCode,
operationName: operationName,
value: roundedValue,
condition: selectedFunctionData?.condition, condition: selectedFunctionData?.condition,
valueDescription: selectedFunctionData?.valueDescription, valueDescription: selectedFunctionData?.valueDescription,
), ),
), ),
); );
}, },
); unit: 'sec',
} dividendOfRange: 1,
stepIncreaseAmount: 1,
static Widget _buildConditionToggle(
BuildContext context,
String? currentCondition,
String selectCode,
AllDevicesModel? device,
String operationName,
DeviceFunctionData? selectedFunctionData,
) {
final conditions = ["<", "==", ">"];
return ToggleButtons(
onPressed: (int index) {
context.read<FunctionBloc>().add(
AddFunction(
functionData: DeviceFunctionData(
entityId: device?.uuid ?? '',
functionCode: selectCode,
operationName: operationName,
condition: conditions[index],
value: selectedFunctionData?.value ?? 0,
valueDescription: selectedFunctionData?.valueDescription,
),
),
);
},
borderRadius: const BorderRadius.all(Radius.circular(8)),
selectedBorderColor: ColorsManager.primaryColorWithOpacity,
selectedColor: Colors.white,
fillColor: ColorsManager.primaryColorWithOpacity,
color: ColorsManager.primaryColorWithOpacity,
constraints: const BoxConstraints(
minHeight: 40.0,
minWidth: 40.0,
),
isSelected:
conditions.map((c) => c == (currentCondition ?? "==")).toList(),
children: conditions.map((c) => Text(c)).toList(),
); );
} }
} }