diff --git a/lib/pages/device_managment/all_devices/view/device_managment_page.dart b/lib/pages/device_managment/all_devices/view/device_managment_page.dart index ffc57131..966d5361 100644 --- a/lib/pages/device_managment/all_devices/view/device_managment_page.dart +++ b/lib/pages/device_managment/all_devices/view/device_managment_page.dart @@ -88,31 +88,32 @@ class DeviceManagementPage extends StatelessWidget with HelperResponsiveLayout { ); }), rightBody: const NavigateHomeGridView(), - scaffoldBody: BlocBuilder( - builder: (context, state) { - if (state is SelectedTabState && state.selectedTab) { - return const RoutinesView(); - } - if (state is ShowCreateRoutineState && state.showCreateRoutine) { - return const CreateNewRoutineView(); - } + scaffoldBody: CreateNewRoutineView(), + // BlocBuilder( + // builder: (context, state) { + // if (state is SelectedTabState && state.selectedTab) { + // return const RoutinesView(); + // } + // if (state is ShowCreateRoutineState && state.showCreateRoutine) { + // return const CreateNewRoutineView(); + // } - return BlocBuilder( - builder: (context, deviceState) { - if (deviceState is DeviceManagementLoading) { - return const Center(child: CircularProgressIndicator()); - } else if (deviceState is DeviceManagementLoaded || - deviceState is DeviceManagementFiltered) { - final devices = (deviceState as dynamic).devices ?? - (deviceState as DeviceManagementFiltered).filteredDevices; + // return BlocBuilder( + // builder: (context, deviceState) { + // if (deviceState is DeviceManagementLoading) { + // return const Center(child: CircularProgressIndicator()); + // } else if (deviceState is DeviceManagementLoaded || + // deviceState is DeviceManagementFiltered) { + // final devices = (deviceState as dynamic).devices ?? + // (deviceState as DeviceManagementFiltered).filteredDevices; - return DeviceManagementBody(devices: devices); - } else { - return const Center(child: Text('Error fetching Devices')); - } - }, - ); - }), + // return DeviceManagementBody(devices: devices); + // } else { + // return const Center(child: Text('Error fetching Devices')); + // } + // }, + // ); + // }), ), ); } diff --git a/lib/pages/routiens/bloc/effective_period/effect_period_bloc.dart b/lib/pages/routiens/bloc/effective_period/effect_period_bloc.dart index 05f63123..b5a293a1 100644 --- a/lib/pages/routiens/bloc/effective_period/effect_period_bloc.dart +++ b/lib/pages/routiens/bloc/effective_period/effect_period_bloc.dart @@ -2,7 +2,10 @@ import 'dart:async'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_web/pages/routiens/bloc/effective_period/effect_period_event.dart'; import 'package:syncrow_web/pages/routiens/bloc/effective_period/effect_period_state.dart'; +import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart'; +import 'package:syncrow_web/pages/routiens/models/create_scene_and_autoamtion/create_automation_model.dart'; import 'package:syncrow_web/utils/constants/app_enum.dart'; +import 'package:syncrow_web/utils/navigation_service.dart'; class EffectPeriodBloc extends Bloc { final daysMap = { @@ -49,9 +52,9 @@ class EffectPeriodBloc extends Bloc { break; } - // BlocProvider.of(NavigationService.navigatorKey.currentContext!).add( - // EffectiveTimePeriodEvent( - // EffectiveTime(start: startTime, end: endTime, loops: state.selectedDaysBinary))); + BlocProvider.of(NavigationService.navigatorKey.currentContext!).add( + EffectiveTimePeriodEvent( + EffectiveTime(start: startTime, end: endTime, loops: state.selectedDaysBinary))); emit(state.copyWith( selectedPeriod: event.period, customStartTime: startTime, customEndTime: endTime)); @@ -68,11 +71,11 @@ class EffectPeriodBloc extends Bloc { final newDaysBinary = daysList.join(); emit(state.copyWith(selectedDaysBinary: newDaysBinary)); - // BlocProvider.of(NavigationService.navigatorKey.currentContext!).add( - // EffectiveTimePeriodEvent(EffectiveTime( - // start: state.customStartTime ?? '00:00', - // end: state.customEndTime ?? '23:59', - // loops: newDaysBinary))); + BlocProvider.of(NavigationService.navigatorKey.currentContext!).add( + EffectiveTimePeriodEvent(EffectiveTime( + start: state.customStartTime ?? '00:00', + end: state.customEndTime ?? '23:59', + loops: newDaysBinary))); } void _onSetCustomTime(SetCustomTime event, Emitter emit) { @@ -94,9 +97,9 @@ class EffectPeriodBloc extends Bloc { emit( state.copyWith(customStartTime: startTime, customEndTime: endTime, selectedPeriod: period)); - // BlocProvider.of(NavigationService.navigatorKey.currentContext!).add( - // EffectiveTimePeriodEvent( - // EffectiveTime(start: startTime, end: endTime, loops: state.selectedDaysBinary))); + BlocProvider.of(NavigationService.navigatorKey.currentContext!).add( + EffectiveTimePeriodEvent( + EffectiveTime(start: startTime, end: endTime, loops: state.selectedDaysBinary))); } void _onResetEffectivePeriod(ResetEffectivePeriod event, Emitter emit) { @@ -106,8 +109,8 @@ class EffectPeriodBloc extends Bloc { customEndTime: '23:59', selectedDaysBinary: '1111111')); - // BlocProvider.of(NavigationService.navigatorKey.currentContext!).add( - // EffectiveTimePeriodEvent(EffectiveTime(start: '00:00', end: '23:59', loops: '1111111'))); + BlocProvider.of(NavigationService.navigatorKey.currentContext!).add( + EffectiveTimePeriodEvent(EffectiveTime(start: '00:00', end: '23:59', loops: '1111111'))); } void _onResetDays(ResetDays event, Emitter emit) { diff --git a/lib/pages/routiens/bloc/routine_bloc/routine_bloc.dart b/lib/pages/routiens/bloc/routine_bloc/routine_bloc.dart index 5eb6bd4c..64872925 100644 --- a/lib/pages/routiens/bloc/routine_bloc/routine_bloc.dart +++ b/lib/pages/routiens/bloc/routine_bloc/routine_bloc.dart @@ -3,7 +3,8 @@ import 'dart:async'; import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; import 'package:flutter/material.dart'; -import 'package:syncrow_web/pages/routiens/models/create_scene/create_scene_model.dart'; +import 'package:syncrow_web/pages/routiens/models/create_scene_and_autoamtion/create_automation_model.dart'; +import 'package:syncrow_web/pages/routiens/models/create_scene_and_autoamtion/create_scene_model.dart'; import 'package:syncrow_web/pages/routiens/models/device_functions.dart'; import 'package:syncrow_web/pages/routiens/models/routine_model.dart'; import 'package:syncrow_web/services/routines_api.dart'; @@ -28,6 +29,8 @@ class RoutineBloc extends Bloc { on(_onCreateScene); on(_onRemoveDragCard); on(_changeOperatorOperator); + on(_onEffectiveTimeEvent); + on(_onCreateAutomation); // on(_onRemoveFunction); // on(_onClearFunctions); } @@ -213,10 +216,119 @@ class RoutineBloc extends Bloc { } } + Future _onCreateAutomation( + CreateAutomationEvent event, Emitter emit) async { + try { + if (state.routineName == null || state.routineName!.isEmpty) { + emit(state.copyWith( + errorMessage: 'Automation name is required', + )); + return; + } + + emit(state.copyWith(isLoading: true)); + + final conditions = state.ifItems + .map((item) { + final functions = + state.selectedFunctions[item['uniqueCustomId']] ?? []; + if (functions.isEmpty) return null; + + final function = functions.first; + return CreateCondition( + code: state.ifItems.indexOf(item) + 1, + entityId: function.entityId, + entityType: 'device_report', + expr: ConditionExpr( + statusCode: function.functionCode, + comparator: function.condition ?? '==', + statusValue: function.value, + ), + ); + }) + .whereType() + .toList(); + + if (conditions.isEmpty) { + emit(state.copyWith( + isLoading: false, + errorMessage: 'At least one condition is required', + )); + return; + } + + final createAutomationModel = CreateAutomationModel( + unitUuid: spaceId, + automationName: state.routineName!, + decisionExpr: state.selectedAutomationOperator, + effectiveTime: state.effectiveTime ?? + EffectiveTime( + start: '00:00', + end: '23:59', + loops: '1111111', + ), + conditions: conditions, + actions: state.thenItems + .map((item) { + final functions = + state.selectedFunctions[item['uniqueCustomId']] ?? []; + if (functions.isEmpty) return null; + + final function = functions.first; + if (function.functionCode == 'automation') { + return CreateSceneAction( + entityId: function.entityId, + actionExecutor: function.value, + executorProperty: null, + ); + } + + if (item['deviceId'] == 'delay') { + return CreateSceneAction( + entityId: function.entityId, + actionExecutor: 'delay', + executorProperty: CreateSceneExecutorProperty( + functionCode: '', + functionValue: '', + delaySeconds: function.value, + ), + ); + } + + return CreateSceneAction( + entityId: function.entityId, + actionExecutor: 'device_issue', + executorProperty: CreateSceneExecutorProperty( + functionCode: function.functionCode, + functionValue: function.value, + delaySeconds: 0, + ), + ); + }) + .whereType() + .toList(), + ); + + final result = await SceneApi.createAutomation(createAutomationModel); + if (result['success']) { + emit(const RoutineState()); + } else { + emit(state.copyWith( + isLoading: false, + errorMessage: result['message'], + )); + } + } catch (e) { + emit(state.copyWith( + isLoading: false, + errorMessage: e.toString(), + )); + } + } + FutureOr _onRemoveDragCard( RemoveDragCard event, Emitter emit) { if (event.isFromThen) { - /// remove element from thenItems at specific index final thenItems = List>.from(state.thenItems); thenItems.removeAt(event.index); emit(state.copyWith(thenItems: thenItems)); @@ -233,4 +345,9 @@ class RoutineBloc extends Bloc { selectedAutomationOperator: event.operator, )); } + + FutureOr _onEffectiveTimeEvent( + EffectiveTimePeriodEvent event, Emitter emit) { + emit(state.copyWith(effectiveTime: event.effectiveTime)); + } } diff --git a/lib/pages/routiens/bloc/routine_bloc/routine_event.dart b/lib/pages/routiens/bloc/routine_bloc/routine_event.dart index 38fd5e30..2a89d1b4 100644 --- a/lib/pages/routiens/bloc/routine_bloc/routine_event.dart +++ b/lib/pages/routiens/bloc/routine_bloc/routine_event.dart @@ -94,4 +94,25 @@ class ChangeAutomationOperator extends RoutineEvent { List get props => [operator]; } +class EffectiveTimePeriodEvent extends RoutineEvent { + final EffectiveTime effectiveTime; + const EffectiveTimePeriodEvent(this.effectiveTime); + @override + List get props => [effectiveTime]; +} + +class CreateAutomationEvent extends RoutineEvent { + // final CreateAutomationModel createAutomationModel; + final String? automationId; + final bool updateAutomation; + + const CreateAutomationEvent({ + //required this.createAutomationModel, + this.automationId, + this.updateAutomation = false, + }); + @override + List get props => []; +} + class ClearFunctions extends RoutineEvent {} diff --git a/lib/pages/routiens/bloc/routine_bloc/routine_state.dart b/lib/pages/routiens/bloc/routine_bloc/routine_state.dart index 8f4da16b..42f584ba 100644 --- a/lib/pages/routiens/bloc/routine_bloc/routine_state.dart +++ b/lib/pages/routiens/bloc/routine_bloc/routine_state.dart @@ -17,6 +17,7 @@ class RoutineState extends Equatable { final bool isTabToRun; final bool isAutomation; final String selectedAutomationOperator; + final EffectiveTime? effectiveTime; const RoutineState({ this.ifItems = const [], @@ -35,43 +36,48 @@ class RoutineState extends Equatable { this.isTabToRun = false, this.isAutomation = false, this.selectedAutomationOperator = 'or', + this.effectiveTime, }); - RoutineState copyWith( - {List>? ifItems, - List>? thenItems, - List? scenes, - List? automations, - Map>? selectedFunctions, - bool? isLoading, - String? errorMessage, - String? routineName, - String? selectedIcon, - String? loadAutomationErrorMessage, - String? loadScenesErrorMessage, - String? searchText, - bool? isTabToRun, - bool? isAutomation, - String? selectedAutomationOperator}) { + RoutineState copyWith({ + List>? ifItems, + List>? thenItems, + List? scenes, + List? automations, + Map>? selectedFunctions, + bool? isLoading, + String? errorMessage, + String? routineName, + String? selectedIcon, + String? loadAutomationErrorMessage, + String? loadScenesErrorMessage, + String? searchText, + bool? isTabToRun, + bool? isAutomation, + String? selectedAutomationOperator, + EffectiveTime? effectiveTime, + }) { return RoutineState( - ifItems: ifItems ?? this.ifItems, - thenItems: thenItems ?? this.thenItems, - scenes: scenes ?? this.scenes, - automations: automations ?? this.automations, - selectedFunctions: selectedFunctions ?? this.selectedFunctions, - isLoading: isLoading ?? this.isLoading, - errorMessage: errorMessage ?? this.errorMessage, - routineName: routineName ?? this.routineName, - selectedIcon: selectedIcon ?? this.selectedIcon, - loadScenesErrorMessage: - loadScenesErrorMessage ?? this.loadScenesErrorMessage, - loadAutomationErrorMessage: - loadAutomationErrorMessage ?? this.loadAutomationErrorMessage, - searchText: searchText ?? this.searchText, - isTabToRun: isTabToRun ?? this.isTabToRun, - isAutomation: isAutomation ?? this.isAutomation, - selectedAutomationOperator: - selectedAutomationOperator ?? this.selectedAutomationOperator); + ifItems: ifItems ?? this.ifItems, + thenItems: thenItems ?? this.thenItems, + scenes: scenes ?? this.scenes, + automations: automations ?? this.automations, + selectedFunctions: selectedFunctions ?? this.selectedFunctions, + isLoading: isLoading ?? this.isLoading, + errorMessage: errorMessage ?? this.errorMessage, + routineName: routineName ?? this.routineName, + selectedIcon: selectedIcon ?? this.selectedIcon, + loadScenesErrorMessage: + loadScenesErrorMessage ?? this.loadScenesErrorMessage, + loadAutomationErrorMessage: + loadAutomationErrorMessage ?? this.loadAutomationErrorMessage, + searchText: searchText ?? this.searchText, + isTabToRun: isTabToRun ?? this.isTabToRun, + isAutomation: isAutomation ?? this.isAutomation, + selectedAutomationOperator: + selectedAutomationOperator ?? this.selectedAutomationOperator, + effectiveTime: effectiveTime ?? this.effectiveTime, + ); } @override @@ -90,6 +96,7 @@ class RoutineState extends Equatable { searchText, isTabToRun, isAutomation, - selectedAutomationOperator + selectedAutomationOperator, + effectiveTime ]; } diff --git a/lib/pages/routiens/helper/save_routine_helper.dart b/lib/pages/routiens/helper/save_routine_helper.dart index 7652554f..c6a8b2aa 100644 --- a/lib/pages/routiens/helper/save_routine_helper.dart +++ b/lib/pages/routiens/helper/save_routine_helper.dart @@ -52,6 +52,35 @@ class SaveRoutineHelper { ), title: const Text('Tab to run'), ), + if (state.isAutomation) + ...state.ifItems.map((item) { + final functions = state.selectedFunctions[ + item['uniqueCustomId']] ?? + []; + return ListTile( + leading: SvgPicture.asset( + item['imagePath'], + width: 22, + height: 22, + ), + title: Text(item['title'], + style: const TextStyle(fontSize: 14)), + subtitle: Wrap( + children: functions + .map((f) => Text( + '${f.operationName}: ${f.value}, ', + style: const TextStyle( + color: ColorsManager + .grayColor, + fontSize: 8), + overflow: + TextOverflow.ellipsis, + maxLines: 3, + )) + .toList(), + ), + ); + }), ], ), ), diff --git a/lib/pages/routiens/models/create_scene_and_autoamtion/create_automation_model.dart b/lib/pages/routiens/models/create_scene_and_autoamtion/create_automation_model.dart new file mode 100644 index 00000000..f7bb1fb5 --- /dev/null +++ b/lib/pages/routiens/models/create_scene_and_autoamtion/create_automation_model.dart @@ -0,0 +1,173 @@ + +import 'dart:convert'; + +import 'package:syncrow_web/pages/routiens/models/create_scene_and_autoamtion/create_scene_model.dart'; + +class CreateAutomationModel { + String unitUuid; + String automationName; + String decisionExpr; + EffectiveTime effectiveTime; + List conditions; + List actions; + + CreateAutomationModel({ + required this.unitUuid, + required this.automationName, + required this.decisionExpr, + required this.effectiveTime, + required this.conditions, + required this.actions, + }); + + CreateAutomationModel copyWith({ + String? unitUuid, + String? automationName, + String? decisionExpr, + EffectiveTime? effectiveTime, + List? conditions, + List? actions, + }) { + return CreateAutomationModel( + unitUuid: unitUuid ?? this.unitUuid, + automationName: automationName ?? this.automationName, + decisionExpr: decisionExpr ?? this.decisionExpr, + effectiveTime: effectiveTime ?? this.effectiveTime, + conditions: conditions ?? this.conditions, + actions: actions ?? this.actions, + ); + } + + Map toMap([String? automationId]) { + return { + if (automationId == null) 'spaceUuid': unitUuid, + 'automationName': automationName, + 'decisionExpr': decisionExpr, + 'effectiveTime': effectiveTime.toMap(), + 'conditions': conditions.map((x) => x.toMap()).toList(), + 'actions': actions.map((x) => x.toMap()).toList(), + }; + } + + factory CreateAutomationModel.fromMap(Map map) { + return CreateAutomationModel( + unitUuid: map['spaceUuid'] ?? '', + automationName: map['automationName'] ?? '', + decisionExpr: map['decisionExpr'] ?? '', + effectiveTime: EffectiveTime.fromMap(map['effectiveTime']), + conditions: List.from( + map['conditions']?.map((x) => CreateCondition.fromMap(x))), + actions: List.from( + map['actions']?.map((x) => CreateSceneAction.fromMap(x))), + ); + } + + String toJson([String? automationId]) => json.encode(toMap(automationId)); + + factory CreateAutomationModel.fromJson(String source) => + CreateAutomationModel.fromMap(json.decode(source)); + + @override + String toString() { + return 'CreateAutomationModel(unitUuid: $unitUuid, automationName: $automationName, decisionExpr: $decisionExpr, effectiveTime: $effectiveTime, conditions: $conditions, actions: $actions)'; + } +} + +class EffectiveTime { + String start; + String end; + String loops; + + EffectiveTime({ + required this.start, + required this.end, + required this.loops, + }); + + Map toMap() { + return { + 'start': start, + 'end': end, + 'loops': loops, + }; + } + + factory EffectiveTime.fromMap(Map map) { + return EffectiveTime( + start: map['start'] ?? '', + end: map['end'] ?? '', + loops: map['loops'] ?? '', + ); + } + + @override + String toString() => 'EffectiveTime(start: $start, end: $end, loops: $loops)'; +} + +class CreateCondition { + int code; + String entityId; + String entityType; + ConditionExpr expr; + + CreateCondition({ + required this.code, + required this.entityId, + required this.entityType, + required this.expr, + }); + + Map toMap() { + return { + 'code': code, + 'entityId': entityId, + 'entityType': entityType, + 'expr': expr.toMap(), + }; + } + + factory CreateCondition.fromMap(Map map) { + return CreateCondition( + code: map['code'] ?? 0, + entityId: map['entityId'] ?? '', + entityType: map['entityType'] ?? '', + expr: ConditionExpr.fromMap(map['expr']), + ); + } + + @override + String toString() => + 'CreateCondition(code: $code, entityId: $entityId, entityType: $entityType, expr: $expr)'; +} + +class ConditionExpr { + String statusCode; + String comparator; + dynamic statusValue; + + ConditionExpr({ + required this.statusCode, + required this.comparator, + required this.statusValue, + }); + + Map toMap() { + return { + 'statusCode': statusCode, + 'comparator': comparator, + 'statusValue': statusValue, + }; + } + + factory ConditionExpr.fromMap(Map map) { + return ConditionExpr( + statusCode: map['statusCode'] ?? '', + comparator: map['comparator'] ?? '', + statusValue: map['statusValue'], + ); + } + + @override + String toString() => + 'ConditionExpr(statusCode: $statusCode, comparator: $comparator, statusValue: $statusValue)'; +} diff --git a/lib/pages/routiens/models/create_scene/create_scene_model.dart b/lib/pages/routiens/models/create_scene_and_autoamtion/create_scene_model.dart similarity index 100% rename from lib/pages/routiens/models/create_scene/create_scene_model.dart rename to lib/pages/routiens/models/create_scene_and_autoamtion/create_scene_model.dart diff --git a/lib/pages/routiens/widgets/dialog_footer.dart b/lib/pages/routiens/widgets/dialog_footer.dart index 90c6baec..15db9732 100644 --- a/lib/pages/routiens/widgets/dialog_footer.dart +++ b/lib/pages/routiens/widgets/dialog_footer.dart @@ -5,12 +5,14 @@ class DialogFooter extends StatelessWidget { final VoidCallback onCancel; final VoidCallback? onConfirm; final bool isConfirmEnabled; + final int? dialogWidth; const DialogFooter({ Key? key, required this.onCancel, required this.onConfirm, required this.isConfirmEnabled, + this.dialogWidth, }) : super(key: key); @override @@ -26,24 +28,23 @@ class DialogFooter extends StatelessWidget { child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - _buildFooterButton( - context, - 'Cancel', - onCancel, - width: isConfirmEnabled ? 299 : 179, - ), - if (isConfirmEnabled) - Row( - children: [ - Container(width: 1, height: 50, color: ColorsManager.greyColor), - _buildFooterButton( - context, - 'Confirm', - onConfirm, - width: 299, - ), - ], + Expanded( + child: _buildFooterButton( + context, + 'Cancel', + onCancel, ), + ), + if (isConfirmEnabled) ...[ + Container(width: 1, height: 50, color: ColorsManager.greyColor), + Expanded( + child: _buildFooterButton( + context, + 'Confirm', + onConfirm, + ), + ), + ], ], ), ); @@ -52,14 +53,12 @@ class DialogFooter extends StatelessWidget { Widget _buildFooterButton( BuildContext context, String text, - VoidCallback? onTap, { - required double width, - }) { + VoidCallback? onTap, + ) { return GestureDetector( onTap: onTap, child: SizedBox( height: 50, - width: width, child: Center( child: Text( text, diff --git a/lib/pages/routiens/widgets/if_container.dart b/lib/pages/routiens/widgets/if_container.dart index a23772d6..57577f64 100644 --- a/lib/pages/routiens/widgets/if_container.dart +++ b/lib/pages/routiens/widgets/if_container.dart @@ -124,34 +124,6 @@ class AutomationOperatorSelector extends StatelessWidget { ), child: Row( children: [ - TextButton( - style: TextButton.styleFrom( - backgroundColor: selectedOperator == 'and' - ? ColorsManager.dialogBlueTitle - : ColorsManager.whiteColors, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(0), - ), - ), - child: Text( - 'All condition is met', - style: context.textTheme.bodyMedium?.copyWith( - color: selectedOperator == 'and' - ? ColorsManager.whiteColors - : ColorsManager.blackColor, - ), - ), - onPressed: () { - context - .read() - .add(const ChangeAutomationOperator(operator: 'and')); - }, - ), - Container( - width: 3, - height: 24, - color: ColorsManager.dividerColor, - ), TextButton( style: TextButton.styleFrom( backgroundColor: selectedOperator == 'or' @@ -175,6 +147,34 @@ class AutomationOperatorSelector extends StatelessWidget { .add(const ChangeAutomationOperator(operator: 'or')); }, ), + Container( + width: 3, + height: 24, + color: ColorsManager.dividerColor, + ), + TextButton( + style: TextButton.styleFrom( + backgroundColor: selectedOperator == 'and' + ? ColorsManager.dialogBlueTitle + : ColorsManager.whiteColors, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(0), + ), + ), + child: Text( + 'All condition is met', + style: context.textTheme.bodyMedium?.copyWith( + color: selectedOperator == 'and' + ? ColorsManager.whiteColors + : ColorsManager.blackColor, + ), + ), + onPressed: () { + context + .read() + .add(const ChangeAutomationOperator(operator: 'and')); + }, + ), ], ), ); diff --git a/lib/pages/routiens/widgets/routine_dialogs/automation_dialog.dart b/lib/pages/routiens/widgets/routine_dialogs/automation_dialog.dart index a789aeb6..c494622a 100644 --- a/lib/pages/routiens/widgets/routine_dialogs/automation_dialog.dart +++ b/lib/pages/routiens/widgets/routine_dialogs/automation_dialog.dart @@ -5,18 +5,19 @@ import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart'; import 'package:syncrow_web/pages/routiens/models/device_functions.dart'; import 'package:syncrow_web/pages/routiens/widgets/dialog_header.dart'; import 'package:syncrow_web/pages/routiens/widgets/dialog_footer.dart'; -import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/constants/assets.dart'; class AutomationDialog extends StatefulWidget { final String automationName; final String automationId; + final String uniqueCustomId; const AutomationDialog({ - Key? key, + super.key, required this.automationName, required this.automationId, - }) : super(key: key); + required this.uniqueCustomId, + }); @override _AutomationDialogState createState() => _AutomationDialogState(); @@ -72,18 +73,19 @@ class _AutomationDialogState extends State { [ DeviceFunctionData( entityId: widget.automationId, - functionCode: '', + functionCode: 'automation', value: _isEnabled, operationName: 'Automation', ), ], - widget.automationId, + widget.uniqueCustomId, ), ); Navigator.of(context).pop(true); }, onCancel: () => Navigator.of(context).pop(false), isConfirmEnabled: true, + dialogWidth: 400, ), ], ), diff --git a/lib/pages/routiens/widgets/then_container.dart b/lib/pages/routiens/widgets/then_container.dart index a5e4e60b..9d729327 100644 --- a/lib/pages/routiens/widgets/then_container.dart +++ b/lib/pages/routiens/widgets/then_container.dart @@ -94,20 +94,21 @@ class ThenContainer extends StatelessWidget { ), ); }, - onWillAcceptWithDetails: (data) { - if (data == null) return false; + // onWillAcceptWithDetails: (data) { + // if (data == null) return false; + // return data.data; - if (state.isTabToRun) { - return data.data['type'] == 'automation'; - } + // // if (state.isTabToRun) { + // // return data.data['type'] == 'automation'; + // // } - if (state.isAutomation) { - return data.data['type'] == 'scene' || - data.data['type'] == 'automation'; - } + // // if (state.isAutomation) { + // // return data.data['type'] == 'scene' || + // // data.data['type'] == 'automation'; + // // } - return data.data['deviceId'] != null; - }, + // // return data.data['deviceId'] != null; + // }, onAcceptWithDetails: (data) async { final uniqueCustomId = const Uuid().v4(); final mutableData = Map.from(data.data); @@ -124,13 +125,16 @@ class ThenContainer extends StatelessWidget { builder: (BuildContext context) => AutomationDialog( automationName: mutableData['name'] ?? 'Automation', automationId: mutableData['deviceId'] ?? '', + uniqueCustomId: uniqueCustomId, ), ); if (result != null) { - context - .read() - .add(AddToThenContainer(mutableData)); + context.read().add(AddToThenContainer({ + ...mutableData, + 'imagePath': Assets.automation, + 'title': mutableData['name'], + })); } return; } diff --git a/lib/services/routines_api.dart b/lib/services/routines_api.dart index 0ce106b2..f92f212f 100644 --- a/lib/services/routines_api.dart +++ b/lib/services/routines_api.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:syncrow_web/pages/routiens/models/create_scene/create_scene_model.dart'; +import 'package:syncrow_web/pages/routiens/models/create_scene_and_autoamtion/create_automation_model.dart'; +import 'package:syncrow_web/pages/routiens/models/create_scene_and_autoamtion/create_scene_model.dart'; import 'package:syncrow_web/pages/routiens/models/icon_model.dart'; import 'package:syncrow_web/pages/routiens/models/routine_model.dart'; import 'package:syncrow_web/services/api/http_service.dart'; @@ -29,23 +30,23 @@ class SceneApi { } } // -// // create automation -// static Future> createAutomation( -// CreateAutomationModel createAutomationModel) async { -// try { -// final response = await _httpService.post( -// path: ApiEndpoints.createAutomation, -// body: createAutomationModel.toMap(), -// showServerMessage: false, -// expectedResponseModel: (json) { -// return json; -// }, -// ); -// return response; -// } catch (e) { -// rethrow; -// } -// } +// create automation + static Future> createAutomation( + CreateAutomationModel createAutomationModel) async { + try { + final response = await _httpService.post( + path: ApiEndpoints.createAutomation, + body: createAutomationModel.toMap(), + showServerMessage: false, + expectedResponseModel: (json) { + return json; + }, + ); + return response; + } catch (e) { + rethrow; + } + } static Future> getIcon() async { final response = await _httpService.get( diff --git a/lib/utils/constants/api_const.dart b/lib/utils/constants/api_const.dart index a5decc3b..4bc0e752 100644 --- a/lib/utils/constants/api_const.dart +++ b/lib/utils/constants/api_const.dart @@ -54,4 +54,5 @@ abstract class ApiEndpoints { static const String getSpaceAutomation = '/automation/{unitUuid}'; static const String getIconScene = '/scene/icon'; static const String createScene = '/scene/tap-to-run'; + static const String createAutomation = '/automation'; }