diff --git a/lib/pages/spaces_management/all_spaces/widgets/sidebar_add_community_button.dart b/lib/pages/spaces_management/all_spaces/widgets/sidebar_add_community_button.dart new file mode 100644 index 00000000..5c769d48 --- /dev/null +++ b/lib/pages/spaces_management/all_spaces/widgets/sidebar_add_community_button.dart @@ -0,0 +1,51 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:syncrow_web/pages/spaces_management/all_spaces/bloc/space_management_bloc.dart'; +import 'package:syncrow_web/pages/spaces_management/all_spaces/bloc/space_management_event.dart'; +import 'package:syncrow_web/pages/spaces_management/create_community/view/create_community_dialog.dart'; +import 'package:syncrow_web/utils/color_manager.dart'; +import 'package:syncrow_web/utils/constants/assets.dart'; + +class SidebarAddCommunityButton extends StatelessWidget { + const SidebarAddCommunityButton({ + required this.existingCommunityNames, + super.key, + }); + + final List existingCommunityNames; + + @override + Widget build(BuildContext context) { + return SizedBox.square( + dimension: 30, + child: IconButton( + style: IconButton.styleFrom( + iconSize: 20, + backgroundColor: ColorsManager.circleImageBackground, + shape: const CircleBorder( + side: BorderSide( + color: ColorsManager.lightGrayBorderColor, + width: 3, + ), + ), + ), + onPressed: () => _showCreateCommunityDialog(context), + icon: SvgPicture.asset(Assets.addIcon), + ), + ); + } + + void _showCreateCommunityDialog(BuildContext context) => showDialog( + context: context, + builder: (context) => CreateCommunityDialog( + isEditMode: false, + existingCommunityNames: existingCommunityNames, + onCreateCommunity: (name, description) { + context.read().add( + CreateCommunityEvent(name, description, context), + ); + }, + ), + ); +} diff --git a/lib/pages/spaces_management/all_spaces/widgets/sidebar_header.dart b/lib/pages/spaces_management/all_spaces/widgets/sidebar_header.dart new file mode 100644 index 00000000..135be109 --- /dev/null +++ b/lib/pages/spaces_management/all_spaces/widgets/sidebar_header.dart @@ -0,0 +1,31 @@ +import 'package:flutter/material.dart'; +import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/sidebar_add_community_button.dart'; +import 'package:syncrow_web/utils/color_manager.dart'; +import 'package:syncrow_web/utils/extension/build_context_x.dart'; +import 'package:syncrow_web/utils/style.dart'; + +class SidebarHeader extends StatelessWidget { + const SidebarHeader({required this.existingCommunityNames, super.key}); + + final List existingCommunityNames; + + @override + Widget build(BuildContext context) { + return Container( + decoration: subSectionContainerDecoration, + padding: const EdgeInsets.all(16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Communities', + style: context.textTheme.titleMedium?.copyWith( + color: ColorsManager.blackColor, + ), + ), + SidebarAddCommunityButton(existingCommunityNames: existingCommunityNames), + ], + ), + ); + } +} diff --git a/lib/pages/spaces_management/all_spaces/widgets/sidebar_widget.dart b/lib/pages/spaces_management/all_spaces/widgets/sidebar_widget.dart index 17566da7..35bb8ad2 100644 --- a/lib/pages/spaces_management/all_spaces/widgets/sidebar_widget.dart +++ b/lib/pages/spaces_management/all_spaces/widgets/sidebar_widget.dart @@ -1,17 +1,15 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flutter_svg/svg.dart'; import 'package:syncrow_web/common/widgets/search_bar.dart'; import 'package:syncrow_web/pages/spaces_management/all_spaces/bloc/space_management_bloc.dart'; import 'package:syncrow_web/pages/spaces_management/all_spaces/bloc/space_management_event.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/pages/spaces_management/all_spaces/widgets/community_tile.dart'; +import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/sidebar_header.dart'; import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/space_tile_widget.dart'; import 'package:syncrow_web/pages/spaces_management/structure_selector/bloc/center_body_bloc.dart'; import 'package:syncrow_web/pages/spaces_management/structure_selector/bloc/center_body_event.dart'; -import 'package:syncrow_web/utils/color_manager.dart'; -import 'package:syncrow_web/utils/constants/assets.dart'; import 'package:syncrow_web/utils/style.dart'; class SidebarWidget extends StatefulWidget { @@ -19,62 +17,59 @@ class SidebarWidget extends StatefulWidget { final String? selectedSpaceUuid; const SidebarWidget({ - super.key, required this.communities, this.selectedSpaceUuid, + super.key, }); @override - _SidebarWidgetState createState() => _SidebarWidgetState(); + State createState() => _SidebarWidgetState(); } class _SidebarWidgetState extends State { - String _searchQuery = ''; // Track search query + String _searchQuery = ''; String? _selectedSpaceUuid; String? _selectedId; @override void initState() { + _selectedId = widget.selectedSpaceUuid; super.initState(); - _selectedId = widget.selectedSpaceUuid; // Initialize with the passed selected space UUID } @override void didUpdateWidget(covariant SidebarWidget oldWidget) { - super.didUpdateWidget(oldWidget); if (widget.selectedSpaceUuid != oldWidget.selectedSpaceUuid) { - setState(() { - _selectedId = widget.selectedSpaceUuid; - }); + setState(() => _selectedId = widget.selectedSpaceUuid); } + super.didUpdateWidget(oldWidget); } - // Function to filter communities based on the search query - List _filterCommunities() { + List _filteredCommunities() { if (_searchQuery.isEmpty) { - // Reset the selected community and space UUIDs if there's no query _selectedSpaceUuid = null; return widget.communities; } - // Filter communities and expand only those that match the query return widget.communities.where((community) { final containsQueryInCommunity = community.name.toLowerCase().contains(_searchQuery.toLowerCase()); - final containsQueryInSpaces = - community.spaces.any((space) => _containsQuery(space, _searchQuery.toLowerCase())); + final containsQueryInSpaces = community.spaces.any((space) => + _containsQuery(space: space, query: _searchQuery.toLowerCase())); return containsQueryInCommunity || containsQueryInSpaces; }).toList(); } - // Helper function to determine if any space or its children match the search query - bool _containsQuery(SpaceModel space, String query) { + bool _containsQuery({ + required SpaceModel space, + required 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(space: child, query: query), + ); - // If the space or any of its children match the query, expand this space if (matchesSpace || matchesChildren) { _selectedSpaceUuid = space.uuid; } @@ -83,79 +78,35 @@ class _SidebarWidgetState extends State { } bool _isSpaceOrChildSelected(SpaceModel space) { - // Return true if the current space or any of its child spaces is selected - if (_selectedSpaceUuid == space.uuid) { - return true; - } - - // Recursively check if any child spaces match the query - for (var child in space.children) { - if (_isSpaceOrChildSelected(child)) { - return true; - } - } - - return false; + final isSpaceSelected = _selectedSpaceUuid == space.uuid; + final anySubSpaceIsSelected = space.children.any(_isSpaceOrChildSelected); + return isSpaceSelected || anySubSpaceIsSelected; } @override Widget build(BuildContext context) { - final filteredCommunities = _filterCommunities(); + final filteredCommunities = _filteredCommunities(); return Container( width: 300, decoration: subSectionContainerDecoration, child: Column( - mainAxisSize: MainAxisSize.min, // Ensures the Column only takes necessary height + mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - // Communities title with the add button - Container( - decoration: subSectionContainerDecoration, - padding: const EdgeInsets.all(16.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text('Communities', - style: Theme.of(context).textTheme.titleMedium?.copyWith( - color: ColorsManager.blackColor, - )), - GestureDetector( - onTap: () => _navigateToBlank(context), - child: Container( - width: 30, - height: 30, - decoration: const BoxDecoration( - color: ColorsManager.whiteColors, - shape: BoxShape.circle, - ), - child: Center( - child: SvgPicture.asset( - Assets.roundedAddIcon, - width: 24, - height: 24, - ), - ), - ), - ), - ], - ), + SidebarHeader( + existingCommunityNames: + widget.communities.map((community) => community.name).toList(), ), - // Search bar CustomSearchBar( - onSearchChanged: (query) { - setState(() { - _searchQuery = query; - }); - }, + onSearchChanged: (query) => setState(() => _searchQuery = query), ), const SizedBox(height: 16), - // Community list Expanded( child: ListView( - children: filteredCommunities.map((community) { - return _buildCommunityTile(context, community); - }).toList(), + children: filteredCommunities + .map((community) => _buildCommunityTile(context, community)) + .toList(), ), ), ], @@ -163,18 +114,7 @@ class _SidebarWidgetState extends State { ); } - void _navigateToBlank(BuildContext context) { - setState(() { - _selectedId = ''; - }); - context.read().add( - NewCommunityEvent(communities: widget.communities), - ); - } - Widget _buildCommunityTile(BuildContext context, CommunityModel community) { - bool hasChildren = community.spaces.isNotEmpty; - return CommunityTile( title: community.name, key: ValueKey(community.uuid), @@ -183,7 +123,7 @@ class _SidebarWidgetState extends State { onItemSelected: () { setState(() { _selectedId = community.uuid; - _selectedSpaceUuid = null; // Update the selected community + _selectedSpaceUuid = null; }); context.read().add(CommunitySelectedEvent()); @@ -192,46 +132,51 @@ class _SidebarWidgetState extends State { SelectCommunityEvent(selectedCommunity: community), ); }, - onExpansionChanged: (String title, bool expanded) { - _handleExpansionChange(community.uuid, expanded); - }, - children: hasChildren - ? community.spaces - .where((space) => (space.status != SpaceStatus.deleted || - space.status != SpaceStatus.parentDeleted)) - .map((space) => _buildSpaceTile(space, community)) - .toList() - : null, + onExpansionChanged: (title, expanded) {}, + children: community.spaces + .where((space) { + final isDeleted = space.status != SpaceStatus.deleted; + final isParentDeleted = space.status != SpaceStatus.parentDeleted; + return (isDeleted || isParentDeleted); + }) + .map((space) => _buildSpaceTile(space: space, community: community)) + .toList(), ); } - Widget _buildSpaceTile(SpaceModel space, CommunityModel community, {int depth = 1}) { - bool isExpandedSpace = _isSpaceOrChildSelected(space); + Widget _buildSpaceTile({ + required SpaceModel space, + required CommunityModel community, + }) { + final spaceIsExpanded = _isSpaceOrChildSelected(space); + final isSelected = _selectedId == space.uuid; return Padding( - padding: EdgeInsets.only(left: depth * 16.0), - child: SpaceTile( - title: space.name, - key: ValueKey(space.uuid), - isSelected: _selectedId == space.uuid, - initiallyExpanded: isExpandedSpace, - onExpansionChanged: (bool expanded) { - _handleExpansionChange(space.uuid ?? '', expanded); - }, - onItemSelected: () { - setState(() { - _selectedId = space.uuid; - _selectedSpaceUuid = space.uuid; - }); + padding: const EdgeInsetsDirectional.only(start: 16.0), + child: SpaceTile( + title: space.name, + key: ValueKey(space.uuid), + isSelected: isSelected, + initiallyExpanded: spaceIsExpanded, + onExpansionChanged: (expanded) {}, + onItemSelected: () { + setState(() { + _selectedId = space.uuid; + _selectedSpaceUuid = space.uuid; + }); - context.read().add( - SelectSpaceEvent(selectedCommunity: community, selectedSpace: space), - ); - }, - children: space.children.isNotEmpty - ? space.children.map((childSpace) => _buildSpaceTile(childSpace, community)).toList() - : [], // Recursively render child spaces if available - )); + context.read().add( + SelectSpaceEvent(selectedCommunity: community, selectedSpace: space), + ); + }, + children: space.children + .map( + (childSpace) => _buildSpaceTile( + space: childSpace, + community: community, + ), + ) + .toList(), + ), + ); } - - void _handleExpansionChange(String uuid, bool expanded) {} }