diff --git a/lib/pages/routiens/bloc/routine_bloc/routine_bloc.dart b/lib/pages/routiens/bloc/routine_bloc/routine_bloc.dart index 9186cc78..ea7428bd 100644 --- a/lib/pages/routiens/bloc/routine_bloc/routine_bloc.dart +++ b/lib/pages/routiens/bloc/routine_bloc/routine_bloc.dart @@ -6,8 +6,11 @@ import 'package:flutter/material.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_details_model.dart'; import 'package:syncrow_web/pages/routiens/models/routine_model.dart'; import 'package:syncrow_web/services/routines_api.dart'; +import 'package:syncrow_web/utils/constants/assets.dart'; +import 'package:uuid/uuid.dart'; part 'routine_event.dart'; part 'routine_state.dart'; @@ -31,6 +34,9 @@ class RoutineBloc extends Bloc { on(_onCreateAutomation); on(_onSetRoutineName); on(_onResetRoutineState); + on(_onGetSceneDetails); + on(_onGetAutomationDetails); + on(_onInitializeRoutineState); // on(_onRemoveFunction); // on(_onClearFunctions); } @@ -390,6 +396,120 @@ class RoutineBloc extends Bloc { emit(state.copyWith(routineName: event.name)); } + Future _onGetSceneDetails(GetSceneDetails event, Emitter emit) async { + try { + emit(state.copyWith( + isLoading: true, + isTabToRun: event.isTabToRun, + isUpdate: true, + sceneId: event.sceneId, + isAutomation: false)); + final sceneDetails = await SceneApi.getSceneDetails(event.sceneId); + add(InitializeRoutineState(sceneDetails)); + } catch (e) { + emit(state.copyWith( + isLoading: false, + errorMessage: 'Failed to load scene details', + )); + } + } + + Future _onGetAutomationDetails( + GetAutomationDetails event, Emitter emit) async { + try { + emit(state.copyWith( + isLoading: true, + isAutomation: event.isAutomation, + automationId: event.automationId, + isTabToRun: false, + isUpdate: true, + )); + final automationDetails = await SceneApi.getAutomationDetails(event.automationId); + add(InitializeRoutineState(automationDetails)); + } catch (e) { + emit(state.copyWith( + isLoading: false, + errorMessage: 'Failed to load automation details', + )); + } + } + + void _onInitializeRoutineState(InitializeRoutineState event, Emitter emit) { + final routineDetails = event.routineDetails; + + // Convert actions to draggable cards for the THEN container + final thenItems = routineDetails.actions.map((action) { + final Map cardData = { + 'entityId': action.entityId, + 'uniqueCustomId': const Uuid().v4(), + 'deviceId': action.actionExecutor == 'delay' ? 'delay' : action.entityId, + 'title': action.actionExecutor == 'delay' ? 'Delay' : 'Device', + // fix this + 'imagePath': action.actionExecutor == 'delay' ? Assets.delay : Assets.logo, + }; + + // Add functions to selectedFunctions + if (action.executorProperty != null) { + final functions = [ + DeviceFunctionData( + entityId: action.entityId, + functionCode: action.executorProperty!.functionCode ?? '', + value: action.executorProperty!.functionValue, + + /// fix this + operationName: action.executorProperty?.functionCode ?? ''), + ]; + state.selectedFunctions[cardData['uniqueCustomId']] = functions; + } + + return cardData; + }).toList() ?? + []; + + // Convert conditions to draggable cards for the IF container + final ifItems = routineDetails.conditions?.map((condition) { + final Map cardData = { + 'entityId': condition.entityId, + 'uniqueCustomId': const Uuid().v4(), + 'deviceId': condition.entityId, + + /// fix this + 'title': 'Device', + + /// fix this + 'imagePath': Assets.logo, + }; + + // Add functions to selectedFunctions + final functions = [ + DeviceFunctionData( + entityId: condition.entityId, + functionCode: condition.expr.statusCode, + value: condition.expr.statusValue, + condition: condition.expr.comparator, + operationName: condition.expr.comparator, + ), + ]; + state.selectedFunctions[cardData['uniqueCustomId']] = functions; + + return cardData; + }).toList() ?? + []; + + emit(state.copyWith( + isLoading: false, + routineName: routineDetails.name, + selectedIcon: routineDetails.iconId, + selectedAutomationOperator: routineDetails.decisionExpr, + effectiveTime: routineDetails.effectiveTime, + isAutomation: routineDetails.conditions != null, + isTabToRun: routineDetails.conditions == null, + thenItems: thenItems, + ifItems: ifItems, + selectedFunctions: Map.from(state.selectedFunctions), + )); + } + RoutineState _resetState() { return const RoutineState( ifItems: [], diff --git a/lib/pages/routiens/bloc/routine_bloc/routine_event.dart b/lib/pages/routiens/bloc/routine_bloc/routine_event.dart index 909e458d..ad93a5ac 100644 --- a/lib/pages/routiens/bloc/routine_bloc/routine_event.dart +++ b/lib/pages/routiens/bloc/routine_bloc/routine_event.dart @@ -125,6 +125,39 @@ class SetRoutineName extends RoutineEvent { List get props => [name]; } +class GetSceneDetails extends RoutineEvent { + final String sceneId; + final bool isUpdate; + final bool isTabToRun; + const GetSceneDetails({ + required this.sceneId, + required this.isUpdate, + required this.isTabToRun, + }); + @override + List get props => [sceneId]; +} + +class GetAutomationDetails extends RoutineEvent { + final String automationId; + final bool isUpdate; + final bool isAutomation; + const GetAutomationDetails({ + required this.automationId, + this.isUpdate = false, + this.isAutomation = false, + }); + @override + List get props => [automationId]; +} + +class InitializeRoutineState extends RoutineEvent { + final RoutineDetailsModel routineDetails; + const InitializeRoutineState(this.routineDetails); + @override + List get props => [routineDetails]; +} + class ResetRoutineState extends RoutineEvent {} 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 b0689f0d..8f8d9b5c 100644 --- a/lib/pages/routiens/bloc/routine_bloc/routine_state.dart +++ b/lib/pages/routiens/bloc/routine_bloc/routine_state.dart @@ -18,6 +18,9 @@ class RoutineState extends Equatable { final bool isAutomation; final String selectedAutomationOperator; final EffectiveTime? effectiveTime; + final String? sceneId; + final String? automationId; + final bool? isUpdate; const RoutineState({ this.ifItems = const [], @@ -37,6 +40,9 @@ class RoutineState extends Equatable { this.isAutomation = false, this.selectedAutomationOperator = 'or', this.effectiveTime, + this.sceneId, + this.automationId, + this.isUpdate, }); RoutineState copyWith({ @@ -56,6 +62,9 @@ class RoutineState extends Equatable { bool? isAutomation, String? selectedAutomationOperator, EffectiveTime? effectiveTime, + String? sceneId, + String? automationId, + bool? isUpdate, }) { return RoutineState( ifItems: ifItems ?? this.ifItems, @@ -67,13 +76,19 @@ class RoutineState extends Equatable { errorMessage: errorMessage ?? this.errorMessage, routineName: routineName ?? this.routineName, selectedIcon: selectedIcon ?? this.selectedIcon, - loadScenesErrorMessage: loadScenesErrorMessage ?? this.loadScenesErrorMessage, - loadAutomationErrorMessage: loadAutomationErrorMessage ?? this.loadAutomationErrorMessage, + loadScenesErrorMessage: + loadScenesErrorMessage ?? this.loadScenesErrorMessage, + loadAutomationErrorMessage: + loadAutomationErrorMessage ?? this.loadAutomationErrorMessage, searchText: searchText ?? this.searchText, isTabToRun: isTabToRun ?? this.isTabToRun, isAutomation: isAutomation ?? this.isAutomation, - selectedAutomationOperator: selectedAutomationOperator ?? this.selectedAutomationOperator, + selectedAutomationOperator: + selectedAutomationOperator ?? this.selectedAutomationOperator, effectiveTime: effectiveTime ?? this.effectiveTime, + sceneId: sceneId ?? this.sceneId, + automationId: automationId ?? this.automationId, + isUpdate: isUpdate ?? this.isUpdate, ); } @@ -94,6 +109,9 @@ class RoutineState extends Equatable { isTabToRun, isAutomation, selectedAutomationOperator, - effectiveTime + effectiveTime, + sceneId, + automationId, + isUpdate ]; } diff --git a/lib/pages/routiens/models/routine_model.dart b/lib/pages/routiens/models/routine_model.dart index fe22a38c..bb3e117b 100644 --- a/lib/pages/routiens/models/routine_model.dart +++ b/lib/pages/routiens/models/routine_model.dart @@ -24,7 +24,14 @@ class ScenesModel { String toRawJson() => json.encode(toJson()); - Uint8List get iconInBytes => base64Decode(icon ?? ''); + Uint8List? get iconInBytes { + if (icon == null || icon?.isEmpty == true) return null; + try { + return base64Decode(icon!); + } catch (e) { + return null; + } + } factory ScenesModel.fromJson(Map json, {bool? isAutomation}) { diff --git a/lib/pages/routiens/view/create_new_routine_view.dart b/lib/pages/routiens/view/create_new_routine_view.dart index 38750991..320eb15d 100644 --- a/lib/pages/routiens/view/create_new_routine_view.dart +++ b/lib/pages/routiens/view/create_new_routine_view.dart @@ -6,8 +6,16 @@ import 'package:syncrow_web/pages/routiens/widgets/then_container.dart'; import 'package:syncrow_web/utils/color_manager.dart'; class CreateNewRoutineView extends StatelessWidget { - const CreateNewRoutineView({super.key}); + final bool isUpdate; + final String? routineId; + final bool isScene; + const CreateNewRoutineView({ + super.key, + this.isUpdate = false, + this.routineId, + this.isScene = true, + }); @override Widget build(BuildContext context) { return Container( diff --git a/lib/pages/routiens/widgets/main_routine_view/fetch_routine_scenes_automation.dart b/lib/pages/routiens/widgets/main_routine_view/fetch_routine_scenes_automation.dart index 031b8f63..375491f7 100644 --- a/lib/pages/routiens/widgets/main_routine_view/fetch_routine_scenes_automation.dart +++ b/lib/pages/routiens/widgets/main_routine_view/fetch_routine_scenes_automation.dart @@ -1,6 +1,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_web/pages/device_managment/all_devices/bloc/switch_tabs/switch_tabs_bloc.dart'; import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart'; +import 'package:syncrow_web/pages/routiens/view/create_new_routine_view.dart'; import 'package:syncrow_web/pages/routiens/widgets/main_routine_view/routine_view_card.dart'; import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/constants/assets.dart'; diff --git a/lib/services/routines_api.dart b/lib/services/routines_api.dart index 1483b8ec..7fc3b1bf 100644 --- a/lib/services/routines_api.dart +++ b/lib/services/routines_api.dart @@ -85,7 +85,7 @@ class SceneApi { List scenes = []; for (var scene in scenesJson) { - scenes.add(ScenesModel.fromJson(scene)); + scenes.add(ScenesModel.fromJson(scene, isAutomation: false)); } return scenes; },