From 0aa029a2fc56da3154c128f9c67bee5e50fcfd66 Mon Sep 17 00:00:00 2001 From: Abdullah Alassaf Date: Mon, 17 Feb 2025 03:32:40 +0300 Subject: [PATCH] Removed static space id and community id in the routine --- lib/common/widgets/search_bar.dart | 26 +- lib/common/widgets/spaces_side_tree.dart | 25 -- lib/main.dart | 9 +- .../view/device_managment_page.dart | 4 +- .../bloc/routine_bloc/routine_bloc.dart | 268 ++++++++---------- .../bloc/routine_bloc/routine_event.dart | 16 +- lib/pages/routines/view/routines_view.dart | 28 +- .../fetch_routine_scenes_automation.dart | 4 - .../routines/widgets/routine_devices.dart | 13 +- .../widgets/scenes_and_automations.dart | 6 +- .../space_tree/bloc/space_tree_bloc.dart | 90 +++--- .../space_tree/bloc/space_tree_state.dart | 13 +- .../space_tree/view/space_tree_view.dart | 1 + 13 files changed, 248 insertions(+), 255 deletions(-) delete mode 100644 lib/common/widgets/spaces_side_tree.dart diff --git a/lib/common/widgets/search_bar.dart b/lib/common/widgets/search_bar.dart index 9d17d1c1..a99ac510 100644 --- a/lib/common/widgets/search_bar.dart +++ b/lib/common/widgets/search_bar.dart @@ -3,18 +3,33 @@ import 'package:flutter_svg/svg.dart'; import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/constants/assets.dart'; -class CustomSearchBar extends StatelessWidget { +class CustomSearchBar extends StatefulWidget { final TextEditingController? controller; final String hintText; + final String? searchQuery; final Function(String)? onSearchChanged; // Callback for search input changes const CustomSearchBar({ super.key, this.controller, + this.searchQuery = '', this.hintText = 'Search', this.onSearchChanged, }); + @override + State createState() => _CustomSearchBarState(); +} + +class _CustomSearchBarState extends State { + @override + void dispose() { + if (widget.controller != null) { + widget.controller!.dispose(); + } + super.dispose(); + } + @override Widget build(BuildContext context) { return Container( @@ -36,16 +51,17 @@ class CustomSearchBar extends StatelessWidget { decoration: BoxDecoration( borderRadius: BorderRadius.circular(12), ), - child: TextField( - controller: controller, + child: TextFormField( + controller: widget.controller, + initialValue: widget.searchQuery, style: const TextStyle( color: Colors.black, ), - onChanged: onSearchChanged, // Call the callback on text change + onChanged: widget.onSearchChanged, // Call the callback on text change decoration: InputDecoration( filled: true, fillColor: ColorsManager.textFieldGreyColor, - hintText: hintText, + hintText: widget.hintText, hintStyle: Theme.of(context).textTheme.bodyLarge!.copyWith( color: ColorsManager.lightGrayColor, fontSize: 12, diff --git a/lib/common/widgets/spaces_side_tree.dart b/lib/common/widgets/spaces_side_tree.dart deleted file mode 100644 index b77b0dc5..00000000 --- a/lib/common/widgets/spaces_side_tree.dart +++ /dev/null @@ -1,25 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart'; - -class SpacesSideTree extends StatefulWidget { - final List communities; - final String? selectedSpaceUuid; - const SpacesSideTree({ - super.key, - required this.communities, - this.selectedSpaceUuid, - }); - - @override - State createState() => _SpacesSideTreeState(); -} - -class _SpacesSideTreeState extends State { - String _searchQuery = ''; - String? _selectedSpaceUuid; - String? _selectedId; - @override - Widget build(BuildContext context) { - return const Placeholder(); - } -} diff --git a/lib/main.dart b/lib/main.dart index ffd18f31..72895e94 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -15,12 +15,12 @@ import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_bloc.da import 'package:syncrow_web/services/locator.dart'; import 'package:syncrow_web/utils/app_routes.dart'; import 'package:syncrow_web/utils/constants/routes_const.dart'; +import 'package:syncrow_web/utils/navigation_service.dart'; import 'package:syncrow_web/utils/theme/theme.dart'; Future main() async { try { - const environment = - String.fromEnvironment('FLAVOR', defaultValue: 'development'); + const environment = String.fromEnvironment('FLAVOR', defaultValue: 'development'); await dotenv.load(fileName: '.env.$environment'); WidgetsFlutterBinding.ensureInitialized(); initialSetup(); @@ -55,8 +55,7 @@ class MyApp extends StatelessWidget { return MultiBlocProvider( providers: [ BlocProvider(create: (context) => projectCubit), - BlocProvider( - create: (context) => HomeBloc(projectCubit)..add(const FetchUserInfo())), + BlocProvider(create: (context) => HomeBloc(projectCubit)..add(const FetchUserInfo())), BlocProvider( create: (context) => VisitorPasswordBloc(projectCubit), ), @@ -77,6 +76,8 @@ class MyApp extends StatelessWidget { PointerDeviceKind.unknown, }, ), + key: NavigationService.navigatorKey, + // scaffoldMessengerKey: NavigationService.snackbarKey, theme: myTheme, routerConfig: _router, )); 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 e336e5f1..1ce42b57 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 @@ -20,7 +20,8 @@ class DeviceManagementPage extends StatelessWidget with HelperResponsiveLayout { return MultiBlocProvider( providers: [ BlocProvider( - create: (context) => DeviceManagementBloc(context.read())..add(FetchDevices(context)), + create: (context) => + DeviceManagementBloc(context.read())..add(FetchDevices(context)), ), ], child: WebScaffold( @@ -42,6 +43,7 @@ class DeviceManagementPage extends StatelessWidget with HelperResponsiveLayout { context .read() .add(const TriggerSwitchTabsEvent(isRoutineTab: false)); + context.read().add(FetchDevices(context)); }, child: Text( 'Devices', diff --git a/lib/pages/routines/bloc/routine_bloc/routine_bloc.dart b/lib/pages/routines/bloc/routine_bloc/routine_bloc.dart index 3a2ef4b0..7cd66a9e 100644 --- a/lib/pages/routines/bloc/routine_bloc/routine_bloc.dart +++ b/lib/pages/routines/bloc/routine_bloc/routine_bloc.dart @@ -4,6 +4,7 @@ import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; import 'package:flutter/material.dart'; import 'package:syncrow_web/pages/common/bloc/project_cubit.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/routines/models/create_scene_and_autoamtion/create_automation_model.dart'; import 'package:syncrow_web/pages/routines/models/create_scene_and_autoamtion/create_scene_model.dart'; @@ -11,18 +12,20 @@ import 'package:syncrow_web/pages/routines/models/delay/delay_fucntions.dart'; import 'package:syncrow_web/pages/routines/models/device_functions.dart'; import 'package:syncrow_web/pages/routines/models/routine_details_model.dart'; import 'package:syncrow_web/pages/routines/models/routine_model.dart'; +import 'package:syncrow_web/pages/space_tree/bloc/space_tree_bloc.dart'; import 'package:syncrow_web/services/devices_mang_api.dart'; import 'package:syncrow_web/services/routines_api.dart'; import 'package:syncrow_web/utils/constants/assets.dart'; import 'package:syncrow_web/utils/constants/temp_const.dart'; +import 'package:syncrow_web/utils/navigation_service.dart'; import 'package:syncrow_web/utils/snack_bar.dart'; import 'package:uuid/uuid.dart'; part 'routine_event.dart'; part 'routine_state.dart'; -String spaceId = '25c96044-fadf-44bb-93c7-3c079e527ce6'; -String communityId = 'aff21a57-2f91-4e5c-b99b-0182c3ab65a9'; +// String spaceId = '25c96044-fadf-44bb-93c7-3c079e527ce6'; +// String communityId = 'aff21a57-2f91-4e5c-b99b-0182c3ab65a9'; class RoutineBloc extends Bloc { final ProjectCubit projectCubit; @@ -58,12 +61,11 @@ class RoutineBloc extends Bloc { TriggerSwitchTabsEvent event, Emitter emit, ) { - emit(state.copyWith( - routineTab: event.isRoutineTab, createRoutineView: false)); + emit(state.copyWith(routineTab: event.isRoutineTab, createRoutineView: false)); add(ResetRoutineState()); if (event.isRoutineTab) { - add(LoadScenes(spaceId, communityId)); - add(LoadAutomation(spaceId)); + add(const LoadScenes()); + add(const LoadAutomation()); } } @@ -85,8 +87,8 @@ class RoutineBloc extends Bloc { final updatedIfItems = List>.from(state.ifItems); // Find the index of the item in teh current itemsList - int index = updatedIfItems.indexWhere( - (map) => map['uniqueCustomId'] == event.item['uniqueCustomId']); + int index = + updatedIfItems.indexWhere((map) => map['uniqueCustomId'] == event.item['uniqueCustomId']); // Replace the map if the index is valid if (index != -1) { updatedIfItems[index] = event.item; @@ -95,21 +97,18 @@ class RoutineBloc extends Bloc { } if (event.isTabToRun) { - emit(state.copyWith( - ifItems: updatedIfItems, isTabToRun: true, isAutomation: false)); + emit(state.copyWith(ifItems: updatedIfItems, isTabToRun: true, isAutomation: false)); } else { - emit(state.copyWith( - ifItems: updatedIfItems, isTabToRun: false, isAutomation: true)); + emit(state.copyWith(ifItems: updatedIfItems, isTabToRun: false, isAutomation: true)); } } - void _onAddToThenContainer( - AddToThenContainer event, Emitter emit) { + void _onAddToThenContainer(AddToThenContainer event, Emitter emit) { final currentItems = List>.from(state.thenItems); // Find the index of the item in teh current itemsList - int index = currentItems.indexWhere( - (map) => map['uniqueCustomId'] == event.item['uniqueCustomId']); + int index = + currentItems.indexWhere((map) => map['uniqueCustomId'] == event.item['uniqueCustomId']); // Replace the map if the index is valid if (index != -1) { currentItems[index] = event.item; @@ -120,26 +119,22 @@ class RoutineBloc extends Bloc { emit(state.copyWith(thenItems: currentItems)); } - void _onAddFunctionsToRoutine( - AddFunctionToRoutine event, Emitter emit) { + void _onAddFunctionsToRoutine(AddFunctionToRoutine event, Emitter emit) { try { if (event.functions.isEmpty) return; - List selectedFunction = - List.from(event.functions); + List selectedFunction = List.from(event.functions); Map> currentSelectedFunctions = Map>.from(state.selectedFunctions); if (currentSelectedFunctions.containsKey(event.uniqueCustomId)) { List currentFunctions = - List.from( - currentSelectedFunctions[event.uniqueCustomId] ?? []); + List.from(currentSelectedFunctions[event.uniqueCustomId] ?? []); List functionCode = []; for (int i = 0; i < selectedFunction.length; i++) { for (int j = 0; j < currentFunctions.length; j++) { - if (selectedFunction[i].functionCode == - currentFunctions[j].functionCode) { + if (selectedFunction[i].functionCode == currentFunctions[j].functionCode) { currentFunctions[j] = selectedFunction[i]; if (!functionCode.contains(currentFunctions[j].functionCode)) { functionCode.add(currentFunctions[j].functionCode); @@ -149,15 +144,13 @@ class RoutineBloc extends Bloc { } for (int i = 0; i < functionCode.length; i++) { - selectedFunction - .removeWhere((code) => code.functionCode == functionCode[i]); + selectedFunction.removeWhere((code) => code.functionCode == functionCode[i]); } - currentSelectedFunctions[event.uniqueCustomId] = - List.from(currentFunctions)..addAll(selectedFunction); + currentSelectedFunctions[event.uniqueCustomId] = List.from(currentFunctions) + ..addAll(selectedFunction); } else { - currentSelectedFunctions[event.uniqueCustomId] = - List.from(event.functions); + currentSelectedFunctions[event.uniqueCustomId] = List.from(event.functions); } emit(state.copyWith(selectedFunctions: currentSelectedFunctions)); @@ -166,21 +159,21 @@ class RoutineBloc extends Bloc { } } - Future _onLoadScenes( - LoadScenes event, Emitter emit) async { + Future _onLoadScenes(LoadScenes event, Emitter emit) async { emit(state.copyWith(isLoading: true, errorMessage: null)); - + List scenes = []; try { final projectUuid = projectCubit.state; - - spaceId = event.spaceId; - communityId = event.communityId; - - List scenes = []; - - if (communityId.isNotEmpty && spaceId.isNotEmpty) { - scenes = await SceneApi.getScenes(event.spaceId, event.communityId, projectUuid ?? TempConst.projectId); + BuildContext context = NavigationService.navigatorKey.currentContext!; + var spaceBloc = context.read(); + for (var communityId in spaceBloc.state.selectedCommunities) { + List spacesList = spaceBloc.state.selectedCommunityAndSpaces[communityId] ?? []; + for (var spaceId in spacesList) { + scenes.addAll( + await SceneApi.getScenes(spaceId, communityId, projectUuid ?? TempConst.projectId)); + } } + emit(state.copyWith( scenes: scenes, isLoading: false, @@ -191,19 +184,22 @@ class RoutineBloc extends Bloc { loadScenesErrorMessage: 'Failed to load scenes', errorMessage: '', loadAutomationErrorMessage: '', - scenes: [])); + scenes: scenes)); } } - Future _onLoadAutomation( - LoadAutomation event, Emitter emit) async { + Future _onLoadAutomation(LoadAutomation event, Emitter emit) async { emit(state.copyWith(isLoading: true, errorMessage: null)); + List automations = []; try { - spaceId = event.spaceId; - List automations = []; - if (spaceId.isNotEmpty) { - automations = await SceneApi.getAutomation(event.spaceId); + BuildContext context = NavigationService.navigatorKey.currentContext!; + var spaceBloc = context.read(); + for (var communityId in spaceBloc.state.selectedCommunities) { + List spacesList = spaceBloc.state.selectedCommunityAndSpaces[communityId] ?? []; + for (var spaceId in spacesList) { + automations.addAll(await SceneApi.getAutomation(spaceId)); + } } emit(state.copyWith( automations: automations, @@ -215,20 +211,18 @@ class RoutineBloc extends Bloc { loadAutomationErrorMessage: 'Failed to load automations', errorMessage: '', loadScenesErrorMessage: '', - automations: [])); + automations: automations)); } } - FutureOr _onSearchRoutines( - SearchRoutines event, Emitter emit) async { + FutureOr _onSearchRoutines(SearchRoutines event, Emitter emit) async { emit(state.copyWith(isLoading: true, errorMessage: null)); await Future.delayed(const Duration(seconds: 1)); emit(state.copyWith(isLoading: false, errorMessage: null)); emit(state.copyWith(searchText: event.query)); } - FutureOr _onAddSelectedIcon( - AddSelectedIcon event, Emitter emit) { + FutureOr _onAddSelectedIcon(AddSelectedIcon event, Emitter emit) { emit(state.copyWith(selectedIcon: event.icon)); } @@ -242,8 +236,7 @@ class RoutineBloc extends Bloc { return actions.last['deviceId'] == 'delay'; } - Future _onCreateScene( - CreateSceneEvent event, Emitter emit) async { + Future _onCreateScene(CreateSceneEvent event, Emitter emit) async { try { // Check if first action is delay // if (_isFirstActionDelay(state.thenItems)) { @@ -256,8 +249,7 @@ class RoutineBloc extends Bloc { if (_isLastActionDelay(state.thenItems)) { emit(state.copyWith( - errorMessage: - 'A delay condition cannot be the only or the last action', + errorMessage: 'A delay condition cannot be the only or the last action', isLoading: false, )); return; @@ -302,8 +294,11 @@ class RoutineBloc extends Bloc { }); }).toList(); + BuildContext context = NavigationService.navigatorKey.currentContext!; + var spaceBloc = context.read(); + final createSceneModel = CreateSceneModel( - spaceUuid: spaceId, + spaceUuid: spaceBloc.state.selectedSpaces[0], iconId: state.selectedIcon ?? '', showInDevice: true, sceneName: state.routineName ?? '', @@ -314,8 +309,8 @@ class RoutineBloc extends Bloc { final result = await SceneApi.createScene(createSceneModel); if (result['success']) { add(ResetRoutineState()); - add(LoadScenes(spaceId, communityId)); - add(LoadAutomation(spaceId)); + add(const LoadScenes()); + add(const LoadAutomation()); } else { emit(state.copyWith( isLoading: false, @@ -330,8 +325,7 @@ class RoutineBloc extends Bloc { } } - Future _onCreateAutomation( - CreateAutomationEvent event, Emitter emit) async { + Future _onCreateAutomation(CreateAutomationEvent event, Emitter emit) async { try { if (state.routineName == null || state.routineName!.isEmpty) { emit(state.copyWith( @@ -352,8 +346,7 @@ class RoutineBloc extends Bloc { if (_isLastActionDelay(state.thenItems)) { emit(state.copyWith( - errorMessage: - 'A delay condition cannot be the only or the last action', + errorMessage: 'A delay condition cannot be the only or the last action', isLoading: false, )); CustomSnackBar.redSnackBar('Cannot have delay as the last action'); @@ -428,9 +421,11 @@ class RoutineBloc extends Bloc { ); }); }).toList(); + BuildContext context = NavigationService.navigatorKey.currentContext!; + var spaceBloc = context.read(); final createAutomationModel = CreateAutomationModel( - spaceUuid: spaceId, + spaceUuid: spaceBloc.state.selectedSpaces[0], automationName: state.routineName ?? '', decisionExpr: state.selectedAutomationOperator, effectiveTime: EffectiveTime( @@ -445,8 +440,8 @@ class RoutineBloc extends Bloc { final result = await SceneApi.createAutomation(createAutomationModel); if (result['success']) { add(ResetRoutineState()); - add(LoadAutomation(spaceId)); - add(LoadScenes(spaceId, communityId)); + add(const LoadAutomation()); + add(const LoadScenes()); } else { emit(state.copyWith( isLoading: false, @@ -463,21 +458,17 @@ class RoutineBloc extends Bloc { } } - FutureOr _onRemoveDragCard( - RemoveDragCard event, Emitter emit) { + FutureOr _onRemoveDragCard(RemoveDragCard event, Emitter emit) { if (event.isFromThen) { final thenItems = List>.from(state.thenItems); - final selectedFunctions = - Map>.from(state.selectedFunctions); + final selectedFunctions = Map>.from(state.selectedFunctions); thenItems.removeAt(event.index); selectedFunctions.remove(event.key); - emit(state.copyWith( - thenItems: thenItems, selectedFunctions: selectedFunctions)); + emit(state.copyWith(thenItems: thenItems, selectedFunctions: selectedFunctions)); } else { final ifItems = List>.from(state.ifItems); - final selectedFunctions = - Map>.from(state.selectedFunctions); + final selectedFunctions = Map>.from(state.selectedFunctions); ifItems.removeAt(event.index); selectedFunctions.remove(event.key); @@ -488,8 +479,7 @@ class RoutineBloc extends Bloc { isAutomation: false, isTabToRun: false)); } else { - emit(state.copyWith( - ifItems: ifItems, selectedFunctions: selectedFunctions)); + emit(state.copyWith(ifItems: ifItems, selectedFunctions: selectedFunctions)); } } } @@ -501,23 +491,18 @@ class RoutineBloc extends Bloc { )); } - FutureOr _onEffectiveTimeEvent( - EffectiveTimePeriodEvent event, Emitter emit) { + FutureOr _onEffectiveTimeEvent(EffectiveTimePeriodEvent event, Emitter emit) { emit(state.copyWith(effectiveTime: event.effectiveTime)); } - FutureOr _onSetRoutineName( - SetRoutineName event, Emitter emit) { + FutureOr _onSetRoutineName(SetRoutineName event, Emitter emit) { emit(state.copyWith( routineName: event.name, )); } - ( - List>, - List>, - Map> - ) _createCardData( + (List>, List>, Map>) + _createCardData( List actions, List? conditions, Map> currentFunctions, @@ -550,8 +535,7 @@ class RoutineBloc extends Bloc { 'deviceId': condition.entityId, 'title': matchingDevice.name ?? condition.entityId, 'productType': condition.entityType, - 'imagePath': - matchingDevice.getDefaultIcon(condition.entityType), + 'imagePath': matchingDevice.getDefaultIcon(condition.entityType), }; final functions = matchingDevice.functions; @@ -587,11 +571,8 @@ class RoutineBloc extends Bloc { final cardData = { 'entityId': action.entityId, 'uniqueCustomId': const Uuid().v4(), - 'deviceId': - action.actionExecutor == 'delay' ? 'delay' : action.entityId, - 'title': action.actionExecutor == 'delay' - ? 'Delay' - : (matchingDevice.name ?? 'Device'), + 'deviceId': action.actionExecutor == 'delay' ? 'delay' : action.entityId, + 'title': action.actionExecutor == 'delay' ? 'Delay' : (matchingDevice.name ?? 'Device'), 'productType': action.productType, 'imagePath': matchingDevice.getDefaultIcon(action.productType), }; @@ -634,8 +615,7 @@ class RoutineBloc extends Bloc { return (thenItems, ifItems, currentFunctions); } - Future _onGetSceneDetails( - GetSceneDetails event, Emitter emit) async { + Future _onGetSceneDetails(GetSceneDetails event, Emitter emit) async { try { emit(state.copyWith( isLoading: true, @@ -683,12 +663,10 @@ class RoutineBloc extends Bloc { if (!deviceCards.containsKey(deviceId)) { deviceCards[deviceId] = { 'entityId': action.entityId, - 'deviceId': - action.actionExecutor == 'delay' ? 'delay' : action.entityId, - 'uniqueCustomId': - action.type == 'automation' || action.actionExecutor == 'delay' - ? const Uuid().v4() - : action.entityId, + 'deviceId': action.actionExecutor == 'delay' ? 'delay' : action.entityId, + 'uniqueCustomId': action.type == 'automation' || action.actionExecutor == 'delay' + ? const Uuid().v4() + : action.entityId, 'title': action.actionExecutor == 'delay' ? 'Delay' : action.type == 'automation' @@ -723,8 +701,7 @@ class RoutineBloc extends Bloc { ), ); // emit(state.copyWith(automationActionExecutor: action.actionExecutor)); - } else if (action.executorProperty != null && - action.actionExecutor != 'delay') { + } else if (action.executorProperty != null && action.actionExecutor != 'delay') { if (!updatedFunctions.containsKey(uniqueCustomId)) { updatedFunctions[uniqueCustomId] = []; } @@ -796,8 +773,7 @@ class RoutineBloc extends Bloc { } } - FutureOr _onResetRoutineState( - ResetRoutineState event, Emitter emit) { + FutureOr _onResetRoutineState(ResetRoutineState event, Emitter emit) { emit(state.copyWith( ifItems: [], thenItems: [], @@ -821,18 +797,21 @@ class RoutineBloc extends Bloc { createRoutineView: false)); } - FutureOr _deleteScene(DeleteScene event, Emitter emit) { + FutureOr _deleteScene(DeleteScene event, Emitter emit) async { try { emit(state.copyWith(isLoading: true)); + BuildContext context = NavigationService.navigatorKey.currentContext!; + var spaceBloc = context.read(); if (state.isTabToRun) { - SceneApi.deleteScene(unitUuid: spaceId, sceneId: state.sceneId ?? ''); + await SceneApi.deleteScene( + unitUuid: spaceBloc.state.selectedSpaces[0], sceneId: state.sceneId ?? ''); } else { - SceneApi.deleteAutomation( - unitUuid: spaceId, automationId: state.automationId ?? ''); + await SceneApi.deleteAutomation( + unitUuid: spaceBloc.state.selectedSpaces[0], automationId: state.automationId ?? ''); } - add(LoadScenes(spaceId, communityId)); - add(LoadAutomation(spaceId)); + add(const LoadScenes()); + add(const LoadAutomation()); add(ResetRoutineState()); emit(state.copyWith(isLoading: false, createRoutineView: false)); } catch (e) { @@ -857,13 +836,21 @@ class RoutineBloc extends Bloc { // } // } - FutureOr _fetchDevices( - FetchDevicesInRoutine event, Emitter emit) async { + FutureOr _fetchDevices(FetchDevicesInRoutine event, Emitter emit) async { emit(state.copyWith(isLoading: true)); try { final projectUuid = projectCubit.state; - final devices = await DevicesManagementApi() - .fetchDevices('', '', projectUuid ?? TempConst.projectId); + List devices = []; + + BuildContext context = NavigationService.navigatorKey.currentContext!; + var spaceBloc = context.read(); + for (var communityId in spaceBloc.state.selectedCommunities) { + List spacesList = spaceBloc.state.selectedCommunityAndSpaces[communityId] ?? []; + for (var spaceId in spacesList) { + devices.addAll(await DevicesManagementApi() + .fetchDevices(communityId, spaceId, projectUuid ?? TempConst.projectId)); + } + } emit(state.copyWith(isLoading: false, devices: devices)); } catch (e) { @@ -871,8 +858,7 @@ class RoutineBloc extends Bloc { } } - FutureOr _onUpdateScene( - UpdateScene event, Emitter emit) async { + FutureOr _onUpdateScene(UpdateScene event, Emitter emit) async { try { // Check if first action is delay // if (_isFirstActionDelay(state.thenItems)) { @@ -886,8 +872,7 @@ class RoutineBloc extends Bloc { if (_isLastActionDelay(state.thenItems)) { emit(state.copyWith( - errorMessage: - 'A delay condition cannot be the only or the last action', + errorMessage: 'A delay condition cannot be the only or the last action', isLoading: false, )); return; @@ -940,12 +925,11 @@ class RoutineBloc extends Bloc { actions: actions, ); - final result = - await SceneApi.updateScene(createSceneModel, state.sceneId ?? ''); + final result = await SceneApi.updateScene(createSceneModel, state.sceneId ?? ''); if (result['success']) { add(ResetRoutineState()); - add(LoadScenes(spaceId, communityId)); - add(LoadAutomation(spaceId)); + add(const LoadScenes()); + add(const LoadAutomation()); } else { emit(state.copyWith( isLoading: false, @@ -960,8 +944,7 @@ class RoutineBloc extends Bloc { } } - FutureOr _onUpdateAutomation( - UpdateAutomation event, Emitter emit) async { + FutureOr _onUpdateAutomation(UpdateAutomation event, Emitter emit) async { try { if (state.routineName == null || state.routineName!.isEmpty) { emit(state.copyWith( @@ -1056,8 +1039,11 @@ class RoutineBloc extends Bloc { }); }).toList(); + BuildContext context = NavigationService.navigatorKey.currentContext!; + var spaceBloc = context.read(); + final createAutomationModel = CreateAutomationModel( - spaceUuid: spaceId, + spaceUuid: spaceBloc.state.selectedSpaces[0], automationName: state.routineName ?? '', decisionExpr: state.selectedAutomationOperator, effectiveTime: EffectiveTime( @@ -1069,13 +1055,13 @@ class RoutineBloc extends Bloc { actions: actions, ); - final result = await SceneApi.updateAutomation( - createAutomationModel, state.automationId ?? ''); + final result = + await SceneApi.updateAutomation(createAutomationModel, state.automationId ?? ''); if (result['success']) { add(ResetRoutineState()); - add(LoadAutomation(spaceId)); - add(LoadScenes(spaceId, communityId)); + add(LoadAutomation()); + add(LoadScenes()); } else { emit(state.copyWith( isLoading: false, @@ -1103,8 +1089,7 @@ class RoutineBloc extends Bloc { thenItems: [], )); - final automationDetails = - await SceneApi.getAutomationDetails(event.automationId); + final automationDetails = await SceneApi.getAutomationDetails(event.automationId); final Map> deviceIfCards = {}; final Map> deviceThenCards = {}; @@ -1172,15 +1157,13 @@ class RoutineBloc extends Bloc { ), ); - final deviceId = action.actionExecutor == 'delay' - ? '${action.entityId}_delay' - : action.entityId; + final deviceId = + action.actionExecutor == 'delay' ? '${action.entityId}_delay' : action.entityId; if (!deviceThenCards.containsKey(deviceId)) { deviceThenCards[deviceId] = { 'entityId': action.entityId, - 'deviceId': - action.actionExecutor == 'delay' ? 'delay' : action.entityId, + 'deviceId': action.actionExecutor == 'delay' ? 'delay' : action.entityId, 'uniqueCustomId': const Uuid().v4(), 'title': action.actionExecutor == 'delay' ? 'Delay' @@ -1211,8 +1194,7 @@ class RoutineBloc extends Bloc { updatedFunctions[uniqueCustomId] = []; } - if (action.executorProperty != null && - action.actionExecutor != 'delay') { + if (action.executorProperty != null && action.actionExecutor != 'delay') { final functions = matchingDevice.functions; final functionCode = action.executorProperty!.functionCode; for (var function in functions) { @@ -1254,14 +1236,10 @@ class RoutineBloc extends Bloc { } } - final ifItems = deviceIfCards.values - .where((card) => card['type'] == 'condition') - .toList(); + final ifItems = deviceIfCards.values.where((card) => card['type'] == 'condition').toList(); final thenItems = deviceThenCards.values .where((card) => - card['type'] == 'action' || - card['type'] == 'automation' || - card['type'] == 'scene') + card['type'] == 'action' || card['type'] == 'automation' || card['type'] == 'scene') .toList(); emit(state.copyWith( diff --git a/lib/pages/routines/bloc/routine_bloc/routine_event.dart b/lib/pages/routines/bloc/routine_bloc/routine_event.dart index e412aae6..c1b2a23f 100644 --- a/lib/pages/routines/bloc/routine_bloc/routine_event.dart +++ b/lib/pages/routines/bloc/routine_bloc/routine_event.dart @@ -27,22 +27,24 @@ class AddToThenContainer extends RoutineEvent { } class LoadScenes extends RoutineEvent { - final String spaceId; - final String communityId; + // final String spaceId; + // final String communityId; + // final BuildContext context; - const LoadScenes(this.spaceId, this.communityId); + const LoadScenes(); @override - List get props => [spaceId, communityId]; + List get props => []; } class LoadAutomation extends RoutineEvent { - final String spaceId; + // final String spaceId; + // final BuildContext context; - const LoadAutomation(this.spaceId); + const LoadAutomation(); @override - List get props => [spaceId]; + List get props => []; } class AddFunctionToRoutine extends RoutineEvent { diff --git a/lib/pages/routines/view/routines_view.dart b/lib/pages/routines/view/routines_view.dart index 43d3b227..0982601e 100644 --- a/lib/pages/routines/view/routines_view.dart +++ b/lib/pages/routines/view/routines_view.dart @@ -20,7 +20,7 @@ class _RoutinesViewState extends State { @override void initState() { super.initState(); - context.read().add(FetchDevicesInRoutine()); + // context.read().add(FetchDevicesInRoutine()); } @override @@ -32,9 +32,12 @@ class _RoutinesViewState extends State { } return Row( children: [ - Expanded( - child: SpaceTreeView( - onSelect: () {}, + Expanded(child: SpaceTreeView( + onSelect: () { + context.read() + ..add(const LoadScenes()) + ..add(const LoadAutomation()); + }, )), Expanded( flex: 4, @@ -59,8 +62,8 @@ class _RoutinesViewState extends State { ), RoutineViewCard( onTap: () { - if (context.read().selectedCommunityId.isNotEmpty && - context.read().selectedSpaceId.isNotEmpty) { + if (context.read().state.selectedCommunities.length == 1 && + context.read().state.selectedSpaces.length == 1) { context.read().add( (ResetRoutineState()), ); @@ -68,7 +71,18 @@ class _RoutinesViewState extends State { const CreateNewRoutineViewEvent(createRoutineView: true), ); } else { - CustomSnackBar.redSnackBar('Please select a space'); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + context.read().state.selectedSpaces.isEmpty + ? 'Please select a space' + : 'Please select only one space to proceed'), + ), + ); + // CustomSnackBar.redSnackBar( + // context.read().state.selectedSpaces.isEmpty + // ? 'Please select a space' + // : 'Please select only one space to proceed'); } }, icon: Icons.add, diff --git a/lib/pages/routines/widgets/main_routine_view/fetch_routine_scenes_automation.dart b/lib/pages/routines/widgets/main_routine_view/fetch_routine_scenes_automation.dart index ed2a9405..718a78b9 100644 --- a/lib/pages/routines/widgets/main_routine_view/fetch_routine_scenes_automation.dart +++ b/lib/pages/routines/widgets/main_routine_view/fetch_routine_scenes_automation.dart @@ -20,10 +20,6 @@ class _FetchRoutineScenesState extends State @override void initState() { super.initState(); - context.read() - ..add(LoadScenes(context.read().selectedSpaceId, - context.read().selectedCommunityId)) - ..add(LoadAutomation(context.read().selectedSpaceId)); } @override diff --git a/lib/pages/routines/widgets/routine_devices.dart b/lib/pages/routines/widgets/routine_devices.dart index 3515cc70..21531ad3 100644 --- a/lib/pages/routines/widgets/routine_devices.dart +++ b/lib/pages/routines/widgets/routine_devices.dart @@ -4,9 +4,20 @@ import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_mo import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart'; import 'package:syncrow_web/pages/routines/widgets/dragable_card.dart'; -class RoutineDevices extends StatelessWidget { +class RoutineDevices extends StatefulWidget { const RoutineDevices({super.key}); + @override + State createState() => _RoutineDevicesState(); +} + +class _RoutineDevicesState extends State { + @override + void initState() { + super.initState(); + context.read().add(FetchDevicesInRoutine()); + } + @override Widget build(BuildContext context) { return BlocBuilder( diff --git a/lib/pages/routines/widgets/scenes_and_automations.dart b/lib/pages/routines/widgets/scenes_and_automations.dart index 2e268b1c..14cb8d61 100644 --- a/lib/pages/routines/widgets/scenes_and_automations.dart +++ b/lib/pages/routines/widgets/scenes_and_automations.dart @@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_web/pages/routines/bloc/routine_bloc/routine_bloc.dart'; import 'package:syncrow_web/pages/routines/widgets/dragable_card.dart'; -import 'package:syncrow_web/pages/space_tree/bloc/space_tree_bloc.dart'; import 'package:syncrow_web/utils/constants/assets.dart'; class ScenesAndAutomations extends StatefulWidget { @@ -19,9 +18,8 @@ class _ScenesAndAutomationsState extends State { void initState() { super.initState(); context.read() - ..add(LoadScenes(context.read().selectedSpaceId, - context.read().selectedCommunityId)) - ..add(LoadAutomation(context.read().selectedSpaceId)); + ..add(const LoadScenes()) + ..add(const LoadAutomation()); } @override diff --git a/lib/pages/space_tree/bloc/space_tree_bloc.dart b/lib/pages/space_tree/bloc/space_tree_bloc.dart index 2cb39fc8..9a0078e3 100644 --- a/lib/pages/space_tree/bloc/space_tree_bloc.dart +++ b/lib/pages/space_tree/bloc/space_tree_bloc.dart @@ -1,3 +1,4 @@ +import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_web/pages/common/bloc/project_cubit.dart'; import 'package:syncrow_web/pages/space_tree/bloc/space_tree_event.dart'; @@ -8,9 +9,13 @@ import 'package:syncrow_web/services/space_mana_api.dart'; import 'package:syncrow_web/utils/constants/temp_const.dart'; class SpaceTreeBloc extends Bloc { - String selectedCommunityId = 'aff21a57-2f91-4e5c-b99b-0182c3ab65a9'; - String selectedSpaceId = '25c96044-fadf-44bb-93c7-3c079e527ce6'; + // String selectedCommunityId = 'aff21a57-2f91-4e5c-b99b-0182c3ab65a9'; + // String selectedSpaceId = '25c96044-fadf-44bb-93c7-3c079e527ce6'; final ProjectCubit projectCubit; + final TextEditingController textController = TextEditingController(); + + // String selectedCommunityId = 'aff21a57-2f91-4e5c-b99b-0182c3ab65a9'; + // String selectedSpaceId = '25c96044-fadf-44bb-93c7-3c079e527ce6'; SpaceTreeBloc(this.projectCubit) : super(const SpaceTreeState()) { on(_fetchSpaces); @@ -26,14 +31,13 @@ class SpaceTreeBloc extends Bloc { try { final projectUuid = projectCubit.state; - List communities = await CommunitySpaceManagementApi() - .fetchCommunities(projectUuid ?? TempConst.projectId); + List communities = + await CommunitySpaceManagementApi().fetchCommunities(projectUuid ?? TempConst.projectId); List updatedCommunities = await Future.wait( communities.map((community) async { List spaces = await CommunitySpaceManagementApi() - .getSpaceHierarchy( - community.uuid, projectUuid ?? TempConst.projectId); + .getSpaceHierarchy(community.uuid, projectUuid ?? TempConst.projectId); return CommunityModel( uuid: community.uuid, @@ -48,19 +52,15 @@ class SpaceTreeBloc extends Bloc { ); emit(state.copyWith( - communitiesList: updatedCommunities, - expandedCommunity: [], - expandedSpaces: [])); + communitiesList: updatedCommunities, expandedCommunity: [], expandedSpaces: [])); } catch (e) { emit(SpaceTreeErrorState('Error loading communities and spaces: $e')); } } - _onCommunityExpanded( - OnCommunityExpanded event, Emitter emit) async { + _onCommunityExpanded(OnCommunityExpanded event, Emitter emit) async { try { - List updatedExpandedCommunityList = - List.from(state.expandedCommunities); + List updatedExpandedCommunityList = List.from(state.expandedCommunities); if (updatedExpandedCommunityList.contains(event.communityId)) { updatedExpandedCommunityList.remove(event.communityId); @@ -92,17 +92,13 @@ class SpaceTreeBloc extends Bloc { } } - _onCommunitySelected( - OnCommunitySelected event, Emitter emit) async { + _onCommunitySelected(OnCommunitySelected event, Emitter emit) async { try { List updatedSelectedCommunities = List.from(state.selectedCommunities.toSet().toList()); - List updatedSelectedSpaces = - List.from(state.selectedSpaces.toSet().toList()); - List updatedSoldChecks = - List.from(state.soldCheck.toSet().toList()); - Map> communityAndSpaces = - Map.from(state.selectedCommunityAndSpaces); + List updatedSelectedSpaces = List.from(state.selectedSpaces.toSet().toList()); + List updatedSoldChecks = List.from(state.soldCheck.toSet().toList()); + Map> communityAndSpaces = Map.from(state.selectedCommunityAndSpaces); List childrenIds = _getAllChildIds(event.children); @@ -133,12 +129,9 @@ class SpaceTreeBloc extends Bloc { try { List updatedSelectedCommunities = List.from(state.selectedCommunities.toSet().toList()); - List updatedSelectedSpaces = - List.from(state.selectedSpaces.toSet().toList()); - List updatedSoldChecks = - List.from(state.soldCheck.toSet().toList()); - Map> communityAndSpaces = - Map.from(state.selectedCommunityAndSpaces); + List updatedSelectedSpaces = List.from(state.selectedSpaces.toSet().toList()); + List updatedSoldChecks = List.from(state.soldCheck.toSet().toList()); + Map> communityAndSpaces = Map.from(state.selectedCommunityAndSpaces); List childrenIds = _getAllChildIds(event.children); bool isChildSelected = false; @@ -158,11 +151,9 @@ class SpaceTreeBloc extends Bloc { updatedSelectedSpaces.addAll(childrenIds); } - List spaces = - _getThePathToChild(event.communityId, event.spaceId); + List spaces = _getThePathToChild(event.communityId, event.spaceId); for (String space in spaces) { - if (!updatedSelectedSpaces.contains(space) && - !updatedSoldChecks.contains(space)) { + if (!updatedSelectedSpaces.contains(space) && !updatedSoldChecks.contains(space)) { updatedSoldChecks.add(space); } } @@ -181,8 +172,7 @@ class SpaceTreeBloc extends Bloc { } updatedSoldChecks.remove(event.spaceId); - List parents = - _getThePathToChild(event.communityId, event.spaceId); + List parents = _getThePathToChild(event.communityId, event.spaceId); if (!_parentSelected(parents, updatedSelectedSpaces)) { updatedSoldChecks.removeWhere(parents.contains); } @@ -195,7 +185,7 @@ class SpaceTreeBloc extends Bloc { communityAndSpaces[event.communityId] = updatedSelectedSpaces; emit(state.copyWith( - selectedCommunities: updatedSelectedCommunities, + selectedCommunities: updatedSelectedCommunities.toSet().toList(), selectedSpaces: updatedSelectedSpaces, soldCheck: updatedSoldChecks, selectedCommunityAndSpaces: communityAndSpaces)); @@ -221,18 +211,18 @@ class SpaceTreeBloc extends Bloc { // Filter communities and expand only those that match the query filteredCommunity = communities.where((community) { - final containsQueryInCommunity = community.name - .toLowerCase() - .contains(event.searchQuery.toLowerCase()); - final containsQueryInSpaces = community.spaces.any( - (space) => _containsQuery(space, event.searchQuery.toLowerCase())); + final containsQueryInCommunity = + community.name.toLowerCase().contains(event.searchQuery.toLowerCase()); + final containsQueryInSpaces = + community.spaces.any((space) => _containsQuery(space, event.searchQuery.toLowerCase())); return containsQueryInCommunity || containsQueryInSpaces; }).toList(); emit(state.copyWith( filteredCommunity: filteredCommunity, - isSearching: event.searchQuery.isNotEmpty)); + isSearching: event.searchQuery.isNotEmpty, + searchQuery: event.searchQuery)); } catch (e) { emit(const SpaceTreeErrorState('Something went wrong')); } @@ -241,8 +231,8 @@ class SpaceTreeBloc extends Bloc { // Helper function to determine if any space or its children match the search query bool _containsQuery(SpaceModel space, String query) { final matchesSpace = space.name.toLowerCase().contains(query); - final matchesChildren = space.children.any((child) => - _containsQuery(child, query)); // Recursive check for children + final matchesChildren = + space.children.any((child) => _containsQuery(child, query)); // Recursive check for children return matchesSpace || matchesChildren; } @@ -256,15 +246,14 @@ class SpaceTreeBloc extends Bloc { return ids; } - bool _anySpacesSelectedInCommunity(String communityId, - List selectedSpaces, List partialCheckedList) { + bool _anySpacesSelectedInCommunity( + String communityId, List selectedSpaces, List partialCheckedList) { bool result = false; for (var community in state.communityList) { if (community.uuid == communityId) { List ids = _getAllChildIds(community.spaces); for (var id in ids) { - result = - selectedSpaces.contains(id) || partialCheckedList.contains(id); + result = selectedSpaces.contains(id) || partialCheckedList.contains(id); if (result) { return result; } @@ -291,8 +280,7 @@ class SpaceTreeBloc extends Bloc { return ids; } - List _getAllParentsIds( - SpaceModel child, String spaceId, List listIds) { + List _getAllParentsIds(SpaceModel child, String spaceId, List listIds) { List ids = listIds; ids.add(child.uuid ?? ''); @@ -313,4 +301,10 @@ class SpaceTreeBloc extends Bloc { ids.removeLast(); return []; } + + @override + Future close() async { + textController.dispose(); + super.close(); + } } diff --git a/lib/pages/space_tree/bloc/space_tree_state.dart b/lib/pages/space_tree/bloc/space_tree_state.dart index 1abd7455..915197dc 100644 --- a/lib/pages/space_tree/bloc/space_tree_state.dart +++ b/lib/pages/space_tree/bloc/space_tree_state.dart @@ -11,6 +11,7 @@ class SpaceTreeState extends Equatable { final List selectedSpaces; final List soldCheck; final bool isSearching; + final String searchQuery; const SpaceTreeState( {this.communityList = const [], @@ -21,7 +22,8 @@ class SpaceTreeState extends Equatable { this.selectedSpaces = const [], this.soldCheck = const [], this.isSearching = false, - this.selectedCommunityAndSpaces = const {}}); + this.selectedCommunityAndSpaces = const {}, + this.searchQuery = ''}); SpaceTreeState copyWith( {List? communitiesList, @@ -32,7 +34,8 @@ class SpaceTreeState extends Equatable { List? selectedSpaces, List? soldCheck, bool? isSearching, - Map>? selectedCommunityAndSpaces}) { + Map>? selectedCommunityAndSpaces, + String? searchQuery}) { return SpaceTreeState( communityList: communitiesList ?? this.communityList, filteredCommunity: filteredCommunity ?? this.filteredCommunity, @@ -42,7 +45,8 @@ class SpaceTreeState extends Equatable { selectedSpaces: selectedSpaces ?? this.selectedSpaces, soldCheck: soldCheck ?? this.soldCheck, isSearching: isSearching ?? this.isSearching, - selectedCommunityAndSpaces: selectedCommunityAndSpaces ?? this.selectedCommunityAndSpaces); + selectedCommunityAndSpaces: selectedCommunityAndSpaces ?? this.selectedCommunityAndSpaces, + searchQuery: searchQuery ?? this.searchQuery); } @override @@ -55,7 +59,8 @@ class SpaceTreeState extends Equatable { selectedSpaces, soldCheck, isSearching, - selectedCommunityAndSpaces + selectedCommunityAndSpaces, + searchQuery ]; } diff --git a/lib/pages/space_tree/view/space_tree_view.dart b/lib/pages/space_tree/view/space_tree_view.dart index de9d088e..da038f7a 100644 --- a/lib/pages/space_tree/view/space_tree_view.dart +++ b/lib/pages/space_tree/view/space_tree_view.dart @@ -39,6 +39,7 @@ class _SpaceTreeViewState extends State { : Column( children: [ CustomSearchBar( + searchQuery: state.searchQuery, onSearchChanged: (query) { context.read().add(SearchQueryEvent(query)); },