Implemented the selection behavior of the side tree

This commit is contained in:
Abdullah Alassaf
2025-01-30 04:03:54 +03:00
parent 2221d9ae7b
commit 43c17d1c18
14 changed files with 446 additions and 501 deletions
+160 -20
View File
@@ -8,21 +8,26 @@ import 'package:syncrow_web/services/space_mana_api.dart';
class SpaceTreeBloc extends Bloc<SpaceTreeEvent, SpaceTreeState> {
String selectedCommunityId = '';
String selectedSpaceId = '';
SpaceTreeBloc() : super(const SpaceTreeState()) {
on<InitialEvent>(_fetchSpaces);
on<OnSelectSpaceEvent>(_onSelectSpace);
on<OnCommunityExpanded>(_onCommunityExpanded);
on<OnSpaceExpanded>(_onSpaceExpanded);
on<OnCommunitySelected>(_onCommunitySelected);
on<OnSpaceSelected>(_onSpaceSelected);
on<SearchQueryEvent>(_onSearch);
}
_fetchSpaces(InitialEvent event, Emitter<SpaceTreeState> emit) async {
emit(SpaceTreeLoadingState());
try {
// _onloadProducts();
List<CommunityModel> communities = await CommunitySpaceManagementApi().fetchCommunities();
List<CommunityModel> updatedCommunities = await Future.wait(
communities.map((community) async {
List<SpaceModel> spaces =
await CommunitySpaceManagementApi().getSpaceHierarchy(community.uuid);
return CommunityModel(
uuid: community.uuid,
createdAt: community.createdAt,
@@ -35,35 +40,170 @@ class SpaceTreeBloc extends Bloc<SpaceTreeEvent, SpaceTreeState> {
}).toList(),
);
if (updatedCommunities.isNotEmpty &&
state.selectedSpace.isEmpty &&
state.selectedCommunity.isEmpty) {
selectedCommunityId = updatedCommunities[0].uuid;
} else {
selectedCommunityId = state.selectedCommunity;
selectedSpaceId = state.selectedSpace;
}
emit(state.copyWith(
communitiesList: updatedCommunities,
selectedCommunity: selectedCommunityId,
selectedSpace: selectedSpaceId));
communitiesList: updatedCommunities, expandedCommunity: [], expandedSpaces: []));
} catch (e) {
emit(SpaceTreeErrorState('Error loading communities and spaces: $e'));
}
}
_onSelectSpace(OnSelectSpaceEvent event, Emitter<SpaceTreeState> emit) async {
_onCommunityExpanded(OnCommunityExpanded event, Emitter<SpaceTreeState> emit) async {
try {
selectedCommunityId = event.communityId;
selectedSpaceId = event.spaceId;
List<String> updatedExpandedCommunityList = List.from(state.expandedCommunities);
if (updatedExpandedCommunityList.contains(event.communityId)) {
updatedExpandedCommunityList.remove(event.communityId);
} else {
updatedExpandedCommunityList.add(event.communityId);
}
emit(state.copyWith(
communitiesList: state.spacesList,
selectedCommunity: event.communityId,
selectedSpace: event.spaceId));
expandedCommunity: updatedExpandedCommunityList,
));
} catch (e) {
emit(const SpaceTreeErrorState('Something went wrong'));
}
}
_onSpaceExpanded(OnSpaceExpanded event, Emitter<SpaceTreeState> emit) async {
try {
List<String> 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<SpaceTreeState> emit) async {
try {
List<String> updatedSelectedCommunities = List.from(state.selectedCommunities);
List<String> updatedSelectedSpaces = List.from(state.selectedSpaces);
List<String> updatedSoldChecks = List.from(state.soldCheck);
List<String> 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<SpaceTreeState> emit) async {
try {
List<String> updatedSelectedCommunities = List.from(state.selectedCommunities);
List<String> updatedSelectedSpaces = List.from(state.selectedSpaces);
List<String> updatedSoldChecks = List.from(state.soldCheck);
List<String> childrenIds = _getAllChildIds(event.children);
// List<String> 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<SpaceTreeState> emit) async {
try {
List<CommunityModel> communities = List.from(state.communityList);
List<CommunityModel> 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<String> _getAllChildIds(List<SpaceModel> spaces) {
List<String> 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<String> ids = _getAllChildIds(community.spaces);
for (var id in ids) {
result = state.selectedSpaces.contains(id);
break;
}
}
}
return result;
}
}
+50 -10
View File
@@ -1,4 +1,5 @@
import 'package:equatable/equatable.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart';
class SpaceTreeEvent extends Equatable {
const SpaceTreeEvent();
@@ -9,16 +10,6 @@ class SpaceTreeEvent extends Equatable {
class InitialEvent extends SpaceTreeEvent {}
class OnSelectSpaceEvent extends SpaceTreeEvent {
final String communityId;
final String spaceId;
const OnSelectSpaceEvent(this.communityId, this.spaceId);
@override
List<Object> get props => [communityId, spaceId];
}
class SearchForSpace extends SpaceTreeEvent {
final String searchQuery;
@@ -27,3 +18,52 @@ class SearchForSpace extends SpaceTreeEvent {
@override
List<Object> get props => [searchQuery];
}
class OnCommunityExpanded extends SpaceTreeEvent {
final String communityId;
const OnCommunityExpanded(this.communityId);
@override
List<Object> get props => [communityId];
}
class OnCommunitySelected extends SpaceTreeEvent {
final String communityId;
final List<SpaceModel> children;
const OnCommunitySelected(this.communityId, this.children);
@override
List<Object> get props => [communityId, children];
}
class OnSpaceExpanded extends SpaceTreeEvent {
final String communityId;
final String spaceId;
const OnSpaceExpanded(this.communityId, this.spaceId);
@override
List<Object> get props => [communityId, spaceId];
}
class OnSpaceSelected extends SpaceTreeEvent {
final String communityId;
final String spaceId;
final List<SpaceModel> children;
const OnSpaceSelected(this.communityId, this.spaceId, this.children);
@override
List<Object> get props => [communityId, spaceId, children];
}
class SearchQueryEvent extends SpaceTreeEvent {
final String searchQuery;
const SearchQueryEvent(this.searchQuery);
@override
List<Object> get props => [searchQuery];
}
@@ -2,23 +2,56 @@ import 'package:equatable/equatable.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
class SpaceTreeState extends Equatable {
final List<CommunityModel> spacesList;
final String selectedSpace;
final String selectedCommunity;
final List<CommunityModel> communityList;
final List<CommunityModel> filteredCommunity;
final List<String> expandedCommunities;
final List<String> expandedSpaces;
final List<String> selectedCommunities;
final List<String> selectedSpaces;
final List<String> soldCheck;
final bool isSearching;
const SpaceTreeState(
{this.spacesList = const [], this.selectedSpace = '', this.selectedCommunity = ''});
{this.communityList = const [],
this.filteredCommunity = const [],
this.expandedCommunities = const [],
this.expandedSpaces = const [],
this.selectedCommunities = const [],
this.selectedSpaces = const [],
this.soldCheck = const [],
this.isSearching = false});
SpaceTreeState copyWith(
{List<CommunityModel>? communitiesList, String? selectedSpace, String? selectedCommunity}) {
{List<CommunityModel>? communitiesList,
List<CommunityModel>? filteredCommunity,
List<String>? expandedSpaces,
List<String>? expandedCommunity,
List<String>? selectedCommunities,
List<String>? selectedSpaces,
List<String>? soldCheck,
bool? isSearching}) {
return SpaceTreeState(
spacesList: communitiesList ?? this.spacesList,
selectedSpace: selectedSpace ?? this.selectedSpace,
selectedCommunity: selectedCommunity ?? this.selectedCommunity);
communityList: communitiesList ?? this.communityList,
filteredCommunity: filteredCommunity ?? this.filteredCommunity,
expandedSpaces: expandedSpaces ?? this.expandedSpaces,
expandedCommunities: expandedCommunity ?? this.expandedCommunities,
selectedCommunities: selectedCommunities ?? this.selectedCommunities,
selectedSpaces: selectedSpaces ?? this.selectedSpaces,
soldCheck: soldCheck ?? this.soldCheck,
isSearching: isSearching ?? this.isSearching);
}
@override
List<Object?> get props => [spacesList, selectedSpace, selectedCommunity];
List<Object?> get props => [
communityList,
filteredCommunity,
expandedSpaces,
expandedCommunities,
selectedCommunities,
selectedSpaces,
soldCheck,
isSearching
];
}
class SpaceTreeLoadingState extends SpaceTreeState {}
@@ -26,6 +59,7 @@ class SpaceTreeLoadingState extends SpaceTreeState {}
class SpaceTreeErrorState extends SpaceTreeState {
final String message;
const SpaceTreeErrorState(this.message);
@override
List<Object?> get props => [message];
}