diff --git a/assets/icons/arrow_down.svg b/assets/icons/arrow_down.svg
new file mode 100644
index 00000000..2b4be77b
--- /dev/null
+++ b/assets/icons/arrow_down.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/icons/arrow_forward.svg b/assets/icons/arrow_forward.svg
new file mode 100644
index 00000000..e5866360
--- /dev/null
+++ b/assets/icons/arrow_forward.svg
@@ -0,0 +1,3 @@
+
diff --git a/lib/pages/roles_and_permission/users_page/bloc/users_bloc.dart b/lib/pages/roles_and_permission/users_page/bloc/users_bloc.dart
index 5de74e4b..0d153804 100644
--- a/lib/pages/roles_and_permission/users_page/bloc/users_bloc.dart
+++ b/lib/pages/roles_and_permission/users_page/bloc/users_bloc.dart
@@ -3,12 +3,18 @@ import 'package:flutter/material.dart';
import 'package:syncrow_web/pages/roles_and_permission/model/roles_user_model.dart';
import 'package:syncrow_web/pages/roles_and_permission/users_page/bloc/users_event.dart';
import 'package:syncrow_web/pages/roles_and_permission/users_page/bloc/users_status.dart';
+import 'package:syncrow_web/pages/roles_and_permission/users_page/model/tree_node_model.dart';
+import 'package:syncrow_web/pages/spaces_management/model/community_model.dart';
+import 'package:syncrow_web/pages/spaces_management/model/space_model.dart';
+import 'package:syncrow_web/services/space_mana_api.dart';
class UsersBloc extends Bloc {
UsersBloc() : super(UsersInitial()) {
on(_getUsers);
on(_changeUserStatus);
on(isCompleteBasicsFun);
+ on(_onLoadCommunityAndSpaces);
+ on(searchTreeNode);
}
List users = [];
@@ -86,9 +92,9 @@ class UsersBloc extends Bloc {
final TextEditingController phoneController = TextEditingController();
final TextEditingController jobTitleController = TextEditingController();
- bool isCompleteBasics = false;
- bool isCompleteRolePermissions = false;
- bool isCompleteSpaces = false;
+ bool? isCompleteBasics;
+ bool? isCompleteRolePermissions;
+ bool? isCompleteSpaces;
int numberBasics = 0;
int numberSpaces = 0;
@@ -102,35 +108,137 @@ class UsersBloc extends Bloc {
phoneController.text.isNotEmpty &&
jobTitleController.text.isNotEmpty;
emit(ChangeStatusSteps());
+ return isCompleteBasics;
}
- // void checkStatus(CheckStepStatus event, Emitter emit) {
- // try {
- // // Check if basic fields are completed
- // isCompleteBasics = firstNameController.text.isNotEmpty &&
- // lastNameController.text.isNotEmpty &&
- // emailController.text.isNotEmpty &&
- // phoneController.text.isNotEmpty &&
- // jobTitleController.text.isNotEmpty;
- // // Emit the updated state
- // if (isCompleteBasics && isCompleteRolePermissions && isCompleteSpaces) {
- // } else {
- // // emit(IncompleteState(
- // // isCompleteBasics, isCompleteRolePermissions, isCompleteSpaces));
- // }
- // } catch (e) {
- // emit(ErrorState(e.toString()));
- // }
- // }
+ isCompleteSpacesFun(CheckStepStatus event, Emitter emit) {
+ emit(UsersLoadingState());
+ isCompleteSpaces = false;
+ emit(ChangeStatusSteps());
+ print('isCompleteBasics==$isCompleteSpaces');
+ return isCompleteSpaces;
+ }
-// Example placeholder methods for role permissions and spaces
bool checkRolePermissions() {
- // Add logic to check if role permissions are completed
- return true; // Replace with actual logic
+ return true;
}
bool checkSpaces() {
- // Add logic to check if spaces are completed
- return true; // Replace with actual logic
+ return true;
+ }
+
+ Future> _fetchSpacesForCommunity(
+ String communityUuid) async {
+ return await CommunitySpaceManagementApi().getSpaceHierarchy(communityUuid);
+ }
+
+ List updatedCommunities = [];
+ List spacesNodes = [];
+ _onLoadCommunityAndSpaces(
+ LoadCommunityAndSpacesEvent event,
+ Emitter emit,
+ ) async {
+ emit(UsersLoadingState()); // Emit loading state
+ try {
+ // Fetch the list of communities
+ List communities =
+ await CommunitySpaceManagementApi().fetchCommunities();
+
+ // Fetch spaces and create TreeNodes for each community
+ updatedCommunities = await Future.wait(
+ communities.map((community) async {
+ // Fetch spaces for the current community
+ List spaces =
+ await _fetchSpacesForCommunity(community.uuid);
+
+ // Recursively build the tree structure
+ spacesNodes = _buildTreeNodes(spaces);
+
+ // Return a TreeNode for the community, with spaces as its children
+ return TreeNode(
+ uuid: community.uuid,
+ title: community.name,
+ children: spacesNodes,
+ isChecked: false, // Initial state; can be updated later
+ isHighlighted: false,
+ isExpanded: true, // Default to expanded for better UX
+ );
+ }).toList(),
+ );
+
+ // Emit the final state with the structured tree
+ emit(ChangeStatusSteps());
+
+ return updatedCommunities; // Return the structured data if needed
+ } catch (e) {
+ // Emit error state in case of failure
+ emit(ErrorState('Error loading communities and spaces: $e'));
+ }
+ }
+
+// Helper function to recursively build tree nodes
+ List _buildTreeNodes(List spaces) {
+ return spaces.map((space) {
+ // If the space has children, recursively build nodes for them
+ List childNodes =
+ space.children != null ? _buildTreeNodes(space.children!) : [];
+
+ // Create a TreeNode for the current space
+ return TreeNode(
+ uuid: space.uuid!,
+ title: space.name,
+ isChecked: false,
+ isHighlighted: false,
+ isExpanded: childNodes.isNotEmpty, // Expand if there are children
+ children: childNodes,
+ );
+ }).toList();
+ }
+
+ void searchTreeNode(SearchAnode event, Emitter emit) {
+ emit(UsersLoadingState()); // Emit loading state
+
+ // Clear all highlights if the search term is empty
+ if (event.searchTerm!.isEmpty) {
+ _clearHighlights(updatedCommunities);
+ } else {
+ // Perform the search and update the highlights
+ _searchAndHighlightNodes(updatedCommunities, event.searchTerm!);
+ }
+
+ // Emit the updated state after processing all nodes
+ emit(ChangeStatusSteps());
+ }
+
+// Helper function to clear all highlights in the tree
+ void _clearHighlights(List nodes) {
+ for (var node in nodes) {
+ node.isHighlighted = false;
+ if (node.children.isNotEmpty) {
+ _clearHighlights(node.children);
+ }
+ }
+ }
+
+// Helper function to search and highlight nodes recursively
+ bool _searchAndHighlightNodes(List nodes, String searchTerm) {
+ bool anyMatch = false;
+
+ for (var node in nodes) {
+ // Check if this node matches the search term
+ bool isMatch =
+ node.title.toLowerCase().contains(searchTerm.toLowerCase());
+
+ // Recursively check children for matches
+ bool childMatch = _searchAndHighlightNodes(node.children, searchTerm);
+
+ // Highlight this node if it matches or any of its children match
+ node.isHighlighted = isMatch || childMatch;
+
+ // Update if any matches were found in this branch
+ anyMatch = anyMatch || node.isHighlighted;
+ }
+
+ return anyMatch;
}
}
diff --git a/lib/pages/roles_and_permission/users_page/bloc/users_event.dart b/lib/pages/roles_and_permission/users_page/bloc/users_event.dart
index 3b679a7e..77890673 100644
--- a/lib/pages/roles_and_permission/users_page/bloc/users_event.dart
+++ b/lib/pages/roles_and_permission/users_page/bloc/users_event.dart
@@ -1,4 +1,5 @@
import 'package:equatable/equatable.dart';
+import 'package:syncrow_web/pages/roles_and_permission/users_page/model/tree_node_model.dart';
sealed class UsersEvent extends Equatable {
const UsersEvent();
@@ -10,6 +11,12 @@ class GetUsers extends UsersEvent {
List