mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-09 22:57:21 +00:00
add_user_dialog
This commit is contained in:
3
assets/icons/arrow_down.svg
Normal file
3
assets/icons/arrow_down.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="8" height="5" viewBox="0 0 8 5" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M8 0.740463C8 0.574789 7.93931 0.408979 7.8179 0.282701C7.57528 0.0297901 7.18168 0.0297901 6.93903 0.282701L4 3.34404L1.06095 0.282701C0.818322 0.0297898 0.424717 0.0297898 0.182084 0.282701C-0.0606947 0.535291 -0.0606947 0.945601 0.182084 1.19819L3.56055 4.71746C3.80318 4.97034 4.1968 4.97034 4.43945 4.71746L7.8179 1.19819C7.93932 1.07191 8 0.906104 8 0.740463Z" fill="#999999" fill-opacity="0.7"/>
|
||||
</svg>
|
After Width: | Height: | Size: 511 B |
3
assets/icons/arrow_forward.svg
Normal file
3
assets/icons/arrow_forward.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="5" height="9" viewBox="0 0 5 9" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0.647445 0.5C0.481771 0.5 0.315961 0.560695 0.189683 0.6821C-0.0632278 0.924716 -0.0632278 1.31832 0.189683 1.56097L3.25102 4.5L0.189683 7.43905C-0.0632278 7.68168 -0.0632278 8.07528 0.189683 8.31792C0.442273 8.56069 0.852583 8.56069 1.10517 8.31792L4.62444 4.93945C4.87732 4.69682 4.87732 4.3032 4.62444 4.06055L1.10517 0.6821C0.978895 0.560678 0.813086 0.5 0.647445 0.5Z" fill="#999999" fill-opacity="0.7"/>
|
||||
</svg>
|
After Width: | Height: | Size: 519 B |
@ -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<UsersEvent, UsersState> {
|
||||
UsersBloc() : super(UsersInitial()) {
|
||||
on<GetUsers>(_getUsers);
|
||||
on<ChangeUserStatus>(_changeUserStatus);
|
||||
on<CheckStepStatus>(isCompleteBasicsFun);
|
||||
on<LoadCommunityAndSpacesEvent>(_onLoadCommunityAndSpaces);
|
||||
on<SearchAnode>(searchTreeNode);
|
||||
}
|
||||
|
||||
List<RolesUserModel> users = [];
|
||||
@ -86,9 +92,9 @@ class UsersBloc extends Bloc<UsersEvent, UsersState> {
|
||||
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<UsersEvent, UsersState> {
|
||||
phoneController.text.isNotEmpty &&
|
||||
jobTitleController.text.isNotEmpty;
|
||||
emit(ChangeStatusSteps());
|
||||
return isCompleteBasics;
|
||||
}
|
||||
|
||||
// void checkStatus(CheckStepStatus event, Emitter<UsersState> 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<UsersState> 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<List<SpaceModel>> _fetchSpacesForCommunity(
|
||||
String communityUuid) async {
|
||||
return await CommunitySpaceManagementApi().getSpaceHierarchy(communityUuid);
|
||||
}
|
||||
|
||||
List<TreeNode> updatedCommunities = [];
|
||||
List<TreeNode> spacesNodes = [];
|
||||
_onLoadCommunityAndSpaces(
|
||||
LoadCommunityAndSpacesEvent event,
|
||||
Emitter<UsersState> emit,
|
||||
) async {
|
||||
emit(UsersLoadingState()); // Emit loading state
|
||||
try {
|
||||
// Fetch the list of communities
|
||||
List<CommunityModel> 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<SpaceModel> 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<TreeNode> _buildTreeNodes(List<SpaceModel> spaces) {
|
||||
return spaces.map((space) {
|
||||
// If the space has children, recursively build nodes for them
|
||||
List<TreeNode> 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<UsersState> 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<TreeNode> 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<TreeNode> 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;
|
||||
}
|
||||
}
|
||||
|
@ -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<Object?> get props => [];
|
||||
}
|
||||
|
||||
class LoadCommunityAndSpacesEvent extends UsersEvent {
|
||||
const LoadCommunityAndSpacesEvent();
|
||||
@override
|
||||
List<Object?> get props => [];
|
||||
}
|
||||
|
||||
class GetBatchStatus extends UsersEvent {
|
||||
final List<String> uuids;
|
||||
const GetBatchStatus(this.uuids);
|
||||
@ -17,6 +24,7 @@ class GetBatchStatus extends UsersEvent {
|
||||
List<Object?> get props => [uuids];
|
||||
}
|
||||
|
||||
//LoadCommunityAndSpacesEvent
|
||||
class ChangeUserStatus extends UsersEvent {
|
||||
final String userId;
|
||||
final String newStatus;
|
||||
@ -33,3 +41,11 @@ class CheckStepStatus extends UsersEvent {
|
||||
@override
|
||||
List<Object?> get props => [steps];
|
||||
}
|
||||
|
||||
class SearchAnode extends UsersEvent {
|
||||
List<TreeNode>? nodes;
|
||||
String? searchTerm;
|
||||
SearchAnode({this.nodes, this.searchTerm});
|
||||
@override
|
||||
List<Object?> get props => [nodes, searchTerm];
|
||||
}
|
||||
|
@ -0,0 +1,17 @@
|
||||
class TreeNode {
|
||||
String uuid;
|
||||
String title;
|
||||
bool isChecked;
|
||||
bool isHighlighted;
|
||||
bool isExpanded;
|
||||
List<TreeNode> children;
|
||||
|
||||
TreeNode({
|
||||
required this.uuid,
|
||||
required this.title,
|
||||
this.isChecked = false,
|
||||
this.isHighlighted = false,
|
||||
this.isExpanded = false,
|
||||
this.children = const [],
|
||||
});
|
||||
}
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:syncrow_web/pages/roles_and_permission/users_page/bloc/users_bloc.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/view/basics_view.dart';
|
||||
import 'package:syncrow_web/pages/roles_and_permission/users_page/view/roles_and_permission.dart';
|
||||
@ -22,7 +23,7 @@ class _AddNewUserDialogState extends State<AddNewUserDialog> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider(
|
||||
create: (BuildContext context) => UsersBloc(),
|
||||
create: (BuildContext context) => UsersBloc()..add(LoadCommunityAndSpacesEvent()),
|
||||
child: BlocConsumer<UsersBloc, UsersState>(
|
||||
listener: (context, state) {},
|
||||
builder: (context, state) {
|
||||
@ -58,9 +59,9 @@ class _AddNewUserDialogState extends State<AddNewUserDialog> {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_buildStepIndicator(1, "Basics", _blocRole),
|
||||
_buildStepIndicator(2, "Spaces", _blocRole),
|
||||
_buildStepIndicator(
|
||||
_buildStep1Indicator(1, "Basics", _blocRole),
|
||||
_buildStep2Indicator(2, "Spaces", _blocRole),
|
||||
_buildStep3Indicator(
|
||||
3, "Role & Permissions", _blocRole),
|
||||
],
|
||||
),
|
||||
@ -120,14 +121,13 @@ class _AddNewUserDialogState extends State<AddNewUserDialog> {
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
));
|
||||
}));
|
||||
),
|
||||
],
|
||||
),
|
||||
));
|
||||
}));
|
||||
}
|
||||
|
||||
// Method to get the form content based on the current step
|
||||
Widget _getFormContent() {
|
||||
switch (currentStep) {
|
||||
case 1:
|
||||
@ -141,22 +141,70 @@ class _AddNewUserDialogState extends State<AddNewUserDialog> {
|
||||
}
|
||||
}
|
||||
|
||||
// Helper method to build step indicators
|
||||
Widget _buildStepIndicator(int step, String label, UsersBloc bloc) {
|
||||
Widget _buildStep2Indicator(int step, String label, UsersBloc bloc) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
currentStep = step;
|
||||
bloc.add(const CheckStepStatus());
|
||||
});
|
||||
},
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(5.0),
|
||||
child: Row(
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
currentStep == step
|
||||
? Assets.currentProcessIcon
|
||||
: bloc.isCompleteSpaces == false
|
||||
? Assets.wrongProcessIcon
|
||||
: Assets.uncomplete_ProcessIcon,
|
||||
width: 25,
|
||||
height: 25,
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Text(
|
||||
label,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
color: currentStep == step
|
||||
? ColorsManager.blackColor
|
||||
: ColorsManager.greyColor,
|
||||
fontWeight: currentStep == step
|
||||
? FontWeight.bold
|
||||
: FontWeight.normal,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (step != 3)
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(5.0),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 12),
|
||||
child: Container(
|
||||
height: 60,
|
||||
width: 1,
|
||||
color: Colors.grey,
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildStep1Indicator(int step, String label, UsersBloc bloc) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
// if (bloc.formKey.currentState?.validate() ?? false) {
|
||||
setState(() {
|
||||
currentStep = step;
|
||||
if (currentStep == 1) {
|
||||
bloc.numberBasics = 1;
|
||||
} else if (currentStep == 2) {
|
||||
bloc.numberSpaces = 2;
|
||||
} else if (currentStep == 3) {
|
||||
bloc.numberRole = 3;
|
||||
}
|
||||
});
|
||||
// }
|
||||
},
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@ -170,12 +218,67 @@ class _AddNewUserDialogState extends State<AddNewUserDialog> {
|
||||
currentStep == step
|
||||
? Assets.currentProcessIcon
|
||||
: bloc.isCompleteBasics == false
|
||||
&& (bloc.numberBasics != 0 ||
|
||||
bloc.numberRole != 0 ||
|
||||
bloc.numberSpaces != 0)
|
||||
? Assets.wrongProcessIcon
|
||||
? Assets.wrongProcessIcon
|
||||
: bloc.isCompleteBasics == true
|
||||
? Assets.completeProcessIcon
|
||||
: Assets.uncomplete_ProcessIcon,
|
||||
|
||||
width: 25,
|
||||
height: 25,
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Text(
|
||||
label,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
color: currentStep == step
|
||||
? ColorsManager.blackColor
|
||||
: ColorsManager.greyColor,
|
||||
fontWeight: currentStep == step
|
||||
? FontWeight.bold
|
||||
: FontWeight.normal,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (step != 3)
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(5.0),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 12),
|
||||
child: Container(
|
||||
height: 60,
|
||||
width: 1,
|
||||
color: Colors.grey,
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildStep3Indicator(int step, String label, UsersBloc bloc) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
currentStep = step;
|
||||
});
|
||||
},
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(5.0),
|
||||
child: Row(
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
currentStep == step
|
||||
? Assets.currentProcessIcon
|
||||
: bloc.isCompleteRolePermissions == false
|
||||
? Assets.wrongProcessIcon
|
||||
: Assets.uncomplete_ProcessIcon,
|
||||
width: 25,
|
||||
height: 25,
|
||||
),
|
||||
|
@ -199,6 +199,8 @@ class DeviceManagement extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _DeviceManagementState extends State<DeviceManagement> {
|
||||
|
||||
|
||||
final List<MainRoleOption> options = [
|
||||
MainRoleOption(
|
||||
id: '1',
|
||||
|
@ -2,7 +2,9 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:syncrow_web/pages/roles_and_permission/users_page/bloc/users_bloc.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/utils/color_manager.dart';
|
||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
||||
@ -68,7 +70,12 @@ class SpacesAccessView extends StatelessWidget {
|
||||
child: TextFormField(
|
||||
style:
|
||||
const TextStyle(color: Colors.black),
|
||||
controller: _blocRole.firstNameController,
|
||||
// controller: _blocRole.firstNameController,
|
||||
onChanged: (value) {
|
||||
_blocRole.add(SearchAnode(
|
||||
nodes: _blocRole.updatedCommunities,
|
||||
searchTerm: value));
|
||||
},
|
||||
decoration: textBoxDecoration(radios: 20)!
|
||||
.copyWith(
|
||||
fillColor: Colors.white,
|
||||
@ -102,7 +109,9 @@ class SpacesAccessView extends StatelessWidget {
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Container(
|
||||
color: ColorsManager.whiteColors,
|
||||
child: TreeView())))
|
||||
child: TreeView(
|
||||
bloc: _blocRole,
|
||||
))))
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -115,90 +124,15 @@ class SpacesAccessView extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class TreeNode {
|
||||
String title;
|
||||
bool isChecked;
|
||||
bool isHighlighted;
|
||||
bool isExpanded; // New property to manage expansion
|
||||
List<TreeNode> children;
|
||||
|
||||
TreeNode({
|
||||
required this.title,
|
||||
this.isChecked = false,
|
||||
this.isHighlighted = false,
|
||||
this.isExpanded = false, // Default to collapsed
|
||||
this.children = const [],
|
||||
});
|
||||
}
|
||||
|
||||
// ignore: must_be_immutable
|
||||
class TreeView extends StatefulWidget {
|
||||
UsersBloc? bloc;
|
||||
TreeView({super.key, this.bloc});
|
||||
@override
|
||||
_TreeViewState createState() => _TreeViewState();
|
||||
}
|
||||
|
||||
class _TreeViewState extends State<TreeView> {
|
||||
List<TreeNode> treeData = [
|
||||
TreeNode(
|
||||
title: 'Downtown Dubai',
|
||||
),
|
||||
TreeNode(title: 'Dubai Creek Harbour', isHighlighted: true),
|
||||
TreeNode(
|
||||
title: 'Dubai Hills Estate',
|
||||
isHighlighted: true,
|
||||
children: [
|
||||
TreeNode(title: 'North Side'),
|
||||
TreeNode(
|
||||
title: 'South Side',
|
||||
isHighlighted: true,
|
||||
children: [
|
||||
TreeNode(title: 'Hills Business Park'),
|
||||
TreeNode(title: 'Park Point'),
|
||||
TreeNode(title: 'Acacia'),
|
||||
TreeNode(
|
||||
title: 'Executive Residence',
|
||||
children: [
|
||||
TreeNode(title: 'Residence I'),
|
||||
TreeNode(
|
||||
title: 'Residence II',
|
||||
children: [
|
||||
TreeNode(title: 'Ground Floor', isHighlighted: true),
|
||||
TreeNode(title: '1st Floor', isHighlighted: true),
|
||||
TreeNode(title: 'Pool', isHighlighted: true),
|
||||
TreeNode(title: 'Gym', isHighlighted: true),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
TreeNode(
|
||||
title: 'South Side',
|
||||
isHighlighted: true,
|
||||
children: [
|
||||
TreeNode(title: 'Hills Business Park'),
|
||||
TreeNode(title: 'Park Point'),
|
||||
TreeNode(title: 'Acacia'),
|
||||
TreeNode(
|
||||
title: 'Executive Residence',
|
||||
children: [
|
||||
TreeNode(title: 'Residence I'),
|
||||
TreeNode(
|
||||
title: 'Residence II',
|
||||
children: [
|
||||
TreeNode(title: 'Ground Floor', isHighlighted: true),
|
||||
TreeNode(title: '1st Floor', isHighlighted: true),
|
||||
TreeNode(title: 'Pool', isHighlighted: true),
|
||||
TreeNode(title: 'Gym', isHighlighted: true),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
];
|
||||
|
||||
Widget _buildTree(List<TreeNode> nodes, {int level = 0}) {
|
||||
return Column(
|
||||
children: nodes.map((node) => _buildNode(node, level: level)).toList(),
|
||||
@ -207,31 +141,14 @@ class _TreeViewState extends State<TreeView> {
|
||||
|
||||
Widget _buildNode(TreeNode node, {int level = 0}) {
|
||||
return Container(
|
||||
color: node.isHighlighted ? Colors.blue.shade100 : Colors.transparent,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(left: level * 8.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
color: node.isHighlighted ? Colors.blue.shade50 : Colors.transparent,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(5.0),
|
||||
child: Row(
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
node.isExpanded = !node.isExpanded; // Toggle expansion
|
||||
});
|
||||
},
|
||||
child: Icon(
|
||||
node.children.isNotEmpty
|
||||
? (node.isExpanded
|
||||
? Icons.arrow_drop_down
|
||||
: Icons.arrow_right)
|
||||
: Icons.arrow_right,
|
||||
color: node.children.isNotEmpty
|
||||
? Colors.black
|
||||
: Colors.transparent,
|
||||
),
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
@ -246,24 +163,49 @@ class _TreeViewState extends State<TreeView> {
|
||||
height: 20,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 15),
|
||||
Expanded(
|
||||
child: Text(
|
||||
node.title,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
color: Colors.black87,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(left: level * 10.0),
|
||||
child: Row(
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
node.isExpanded = !node.isExpanded;
|
||||
});
|
||||
},
|
||||
child: SizedBox(
|
||||
child: SvgPicture.asset(
|
||||
node.children.isNotEmpty
|
||||
? (node.isExpanded
|
||||
? Assets.arrowDown
|
||||
: Assets.arrowForward)
|
||||
: Assets.arrowForward,
|
||||
fit: BoxFit.none,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 20),
|
||||
Text(
|
||||
node.title,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
color: node.isHighlighted
|
||||
? ColorsManager.blackColor
|
||||
: ColorsManager.textGray,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (node.isExpanded && node.children.isNotEmpty)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 24.0),
|
||||
child: _buildTree(node.children, level: level + 1),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (node.isExpanded && node.children.isNotEmpty)
|
||||
_buildTree(node.children, level: level + 1),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
@ -308,7 +250,7 @@ class _TreeViewState extends State<TreeView> {
|
||||
|
||||
// Update the checkbox state for parent nodes
|
||||
void _updateParentCheckStatus(TreeNode node) {
|
||||
TreeNode? parent = _findParent(treeData, node);
|
||||
TreeNode? parent = _findParent(widget.bloc!.updatedCommunities, node);
|
||||
if (parent != null) {
|
||||
setState(() {
|
||||
parent.isChecked = _areAllChildrenChecked(parent);
|
||||
@ -332,7 +274,7 @@ class _TreeViewState extends State<TreeView> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SingleChildScrollView(
|
||||
child: _buildTree(treeData),
|
||||
child: _buildTree(widget.bloc!.updatedCommunities),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -252,6 +252,7 @@ class CommunitySpaceManagementApi {
|
||||
path: ApiEndpoints.getSpaceHierarchy
|
||||
.replaceAll('{communityId}', communityId),
|
||||
expectedResponseModel: (json) {
|
||||
print('=-=-=-=$json');
|
||||
final spaceModels = (json['data'] as List)
|
||||
.map((spaceJson) => SpaceModel.fromJson(spaceJson))
|
||||
.toList();
|
||||
|
@ -391,4 +391,8 @@ class Assets {
|
||||
'assets/icons/uncompleate_process_icon.svg';
|
||||
static const String wrongProcessIcon =
|
||||
'assets/icons/wrong_process_icon.svg';
|
||||
static const String arrowForward =
|
||||
'assets/icons/arrow_forward.svg';
|
||||
static const String arrowDown =
|
||||
'assets/icons/arrow_down.svg';
|
||||
}
|
||||
|
Reference in New Issue
Block a user