import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_web/pages/space_tree/bloc/space_tree_event.dart'; import 'package:syncrow_web/pages/space_tree/bloc/space_tree_state.dart'; import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart'; import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart'; import 'package:syncrow_web/services/space_mana_api.dart'; class SpaceTreeBloc extends Bloc { String selectedCommunityId = ''; String selectedSpaceId = ''; SpaceTreeBloc() : super(const SpaceTreeState()) { on(_fetchSpaces); on(_onCommunityExpanded); on(_onSpaceExpanded); on(_onCommunitySelected); on(_onSpaceSelected); on(_onSearch); } _fetchSpaces(InitialEvent event, Emitter emit) async { emit(SpaceTreeLoadingState()); try { List communities = await CommunitySpaceManagementApi().fetchCommunities(); List updatedCommunities = await Future.wait( communities.map((community) async { List spaces = await CommunitySpaceManagementApi().getSpaceHierarchy(community.uuid); return CommunityModel( uuid: community.uuid, createdAt: community.createdAt, updatedAt: community.updatedAt, name: community.name, description: community.description, spaces: spaces, region: community.region, ); }).toList(), ); emit(state.copyWith( communitiesList: updatedCommunities, expandedCommunity: [], expandedSpaces: [])); } catch (e) { emit(SpaceTreeErrorState('Error loading communities and spaces: $e')); } } _onCommunityExpanded(OnCommunityExpanded event, Emitter emit) async { try { List updatedExpandedCommunityList = List.from(state.expandedCommunities); if (updatedExpandedCommunityList.contains(event.communityId)) { updatedExpandedCommunityList.remove(event.communityId); } else { updatedExpandedCommunityList.add(event.communityId); } emit(state.copyWith( expandedCommunity: updatedExpandedCommunityList, )); } catch (e) { emit(const SpaceTreeErrorState('Something went wrong')); } } _onSpaceExpanded(OnSpaceExpanded event, Emitter emit) async { try { List updatedExpandedSpacesList = List.from(state.expandedSpaces); if (updatedExpandedSpacesList.contains(event.spaceId)) { updatedExpandedSpacesList.remove(event.spaceId); } else { updatedExpandedSpacesList.add(event.spaceId); } emit(state.copyWith(expandedSpaces: updatedExpandedSpacesList)); } catch (e) { emit(const SpaceTreeErrorState('Something went wrong')); } } _onCommunitySelected(OnCommunitySelected event, Emitter emit) async { try { List updatedSelectedCommunities = List.from(state.selectedCommunities); List updatedSelectedSpaces = List.from(state.selectedSpaces); List updatedSoldChecks = List.from(state.soldCheck); List childrenIds = _getAllChildIds(event.children); if (!updatedSelectedCommunities.contains(event.communityId)) { // Select the community and all its children updatedSelectedCommunities.add(event.communityId); updatedSelectedSpaces.addAll(childrenIds); } else { // Unselect the community and all its children updatedSelectedCommunities.remove(event.communityId); updatedSelectedSpaces.removeWhere(childrenIds.contains); updatedSoldChecks.removeWhere(childrenIds.contains); } emit(state.copyWith( selectedCommunities: updatedSelectedCommunities, selectedSpaces: updatedSelectedSpaces, soldCheck: updatedSoldChecks)); } catch (e) { emit(const SpaceTreeErrorState('Something went wrong')); } } _onSpaceSelected(OnSpaceSelected event, Emitter emit) async { try { List updatedSelectedCommunities = List.from(state.selectedCommunities); List updatedSelectedSpaces = List.from(state.selectedSpaces); List updatedSoldChecks = List.from(state.soldCheck); List childrenIds = _getAllChildIds(event.children); // List childrenIds = _getAllChildSpaceIds(event.communityId); if (!updatedSelectedSpaces.contains(event.spaceId) && !updatedSoldChecks.contains(event.spaceId)) { // First click: Select the space and all its children updatedSelectedSpaces.add(event.spaceId); updatedSelectedCommunities.add(event.communityId); if (childrenIds.isNotEmpty) { updatedSelectedSpaces.addAll(childrenIds); } } else if (!updatedSoldChecks.contains(event.spaceId) && childrenIds.isNotEmpty) { // Second click: Unselect space but keep children updatedSelectedSpaces.remove(event.spaceId); updatedSoldChecks.add(event.spaceId); } else { // Third click: Unselect space and all its children if (!_anySpacesSelectedInCommunity(event.communityId)) { updatedSelectedCommunities.remove(event.communityId); } updatedSelectedSpaces.remove(event.spaceId); if (childrenIds.isNotEmpty) { updatedSelectedSpaces.removeWhere(childrenIds.contains); } updatedSoldChecks.remove(event.spaceId); } emit(state.copyWith( selectedCommunities: updatedSelectedCommunities, selectedSpaces: updatedSelectedSpaces, soldCheck: updatedSoldChecks)); emit(state.copyWith(selectedSpaces: updatedSelectedSpaces)); } catch (e) { emit(const SpaceTreeErrorState('Something went wrong')); } } _onSearch(SearchQueryEvent event, Emitter emit) async { try { List communities = List.from(state.communityList); List filteredCommunity = []; // 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())); return containsQueryInCommunity || containsQueryInSpaces; }).toList(); emit(state.copyWith( filteredCommunity: filteredCommunity, isSearching: event.searchQuery.isNotEmpty)); } catch (e) { emit(const SpaceTreeErrorState('Something went wrong')); } } // 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 return matchesSpace || matchesChildren; } List _getAllChildIds(List spaces) { List ids = []; for (var child in spaces) { ids.add(child.uuid!); ids.addAll(_getAllChildIds(child.children)); } return ids; } bool _anySpacesSelectedInCommunity(String communityId) { bool result = false; for (var community in state.communityList) { if (community.uuid == communityId) { List ids = _getAllChildIds(community.spaces); for (var id in ids) { result = state.selectedSpaces.contains(id); break; } } } return result; } }