Add SpacesRecursiveHelper for recursive space updates and deletions; refactor CommunityStructureHeader to use CommunityStructureHeaderActionButtonsComposer for improved action handling.

This commit is contained in:
Faris Armoush
2025-07-14 14:59:34 +03:00
parent 3bee17c574
commit beb33e37fa
3 changed files with 118 additions and 65 deletions

View File

@ -0,0 +1,41 @@
import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/models/space_model.dart';
import 'package:syncrow_web/pages/space_management_v2/modules/space_details/domain/models/space_details_model.dart';
abstract final class SpacesRecursiveHelper {
static List<SpaceModel> recusrivelyUpdate(
List<SpaceModel> spaces,
SpaceDetailsModel updatedSpace,
) {
return spaces.map((space) {
if (space.uuid == updatedSpace.uuid) {
return space.copyWith(
spaceName: updatedSpace.spaceName,
icon: updatedSpace.icon,
);
}
if (space.children.isNotEmpty) {
return space.copyWith(
children: recusrivelyUpdate(space.children, updatedSpace),
);
}
return space;
}).toList();
}
static List<SpaceModel> recusrivelyDelete(
List<SpaceModel> spaces,
String spaceUuid,
) {
final s = spaces.map((space) {
if (space.uuid == spaceUuid) return null;
if (space.children.isNotEmpty) {
return space.copyWith(
children: recusrivelyDelete(space.children, spaceUuid),
);
}
return space;
}).toList();
return s.whereType<SpaceModel>().toList();
}
}

View File

@ -2,42 +2,17 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/svg.dart'; import 'package:flutter_svg/svg.dart';
import 'package:syncrow_web/pages/space_management_v2/main_module/shared/helpers/space_management_community_dialog_helper.dart'; import 'package:syncrow_web/pages/space_management_v2/main_module/shared/helpers/space_management_community_dialog_helper.dart';
import 'package:syncrow_web/pages/space_management_v2/main_module/widgets/community_structure_header_action_buttons.dart'; import 'package:syncrow_web/pages/space_management_v2/main_module/widgets/community_structure_header_action_buttons_composer.dart';
import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/models/space_model.dart';
import 'package:syncrow_web/pages/space_management_v2/modules/communities/presentation/bloc/communities_bloc.dart';
import 'package:syncrow_web/pages/space_management_v2/modules/communities/presentation/communities_tree_selection_bloc/communities_tree_selection_bloc.dart'; import 'package:syncrow_web/pages/space_management_v2/modules/communities/presentation/communities_tree_selection_bloc/communities_tree_selection_bloc.dart';
import 'package:syncrow_web/pages/space_management_v2/modules/delete_space/presentation/widgets/delete_space_dialog.dart';
import 'package:syncrow_web/pages/space_management_v2/modules/space_details/domain/models/space_details_model.dart';
import 'package:syncrow_web/pages/space_management_v2/modules/space_details/presentation/helpers/space_details_dialog_helper.dart';
import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/constants/assets.dart'; import 'package:syncrow_web/utils/constants/assets.dart';
import 'package:syncrow_web/utils/extension/build_context_x.dart';
class CommunityStructureHeader extends StatelessWidget { class CommunityStructureHeader extends StatelessWidget {
const CommunityStructureHeader({super.key}); const CommunityStructureHeader({super.key});
List<SpaceModel> _updateRecursive(
List<SpaceModel> spaces,
SpaceDetailsModel updatedSpace,
) {
return spaces.map((space) {
if (space.uuid == updatedSpace.uuid) {
return space.copyWith(
spaceName: updatedSpace.spaceName,
icon: updatedSpace.icon,
);
}
if (space.children.isNotEmpty) {
return space.copyWith(
children: _updateRecursive(space.children, updatedSpace),
);
}
return space;
}).toList();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final theme = Theme.of(context);
final screenWidth = MediaQuery.of(context).size.width; final screenWidth = MediaQuery.of(context).size.width;
return Container( return Container(
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 16.0), padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 16.0),
@ -58,7 +33,7 @@ class CommunityStructureHeader extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Expanded( Expanded(
child: _buildCommunityInfo(context, theme, screenWidth), child: _buildCommunityInfo(context, screenWidth),
), ),
const SizedBox(width: 16), const SizedBox(width: 16),
], ],
@ -68,8 +43,7 @@ class CommunityStructureHeader extends StatelessWidget {
); );
} }
Widget _buildCommunityInfo( Widget _buildCommunityInfo(BuildContext context, double screenWidth) {
BuildContext context, ThemeData theme, double screenWidth) {
final selectedCommunity = final selectedCommunity =
context.watch<CommunitiesTreeSelectionBloc>().state.selectedCommunity; context.watch<CommunitiesTreeSelectionBloc>().state.selectedCommunity;
final selectedSpace = final selectedSpace =
@ -79,7 +53,7 @@ class CommunityStructureHeader extends StatelessWidget {
children: [ children: [
Text( Text(
'Community Structure', 'Community Structure',
style: theme.textTheme.headlineLarge?.copyWith( style: context.textTheme.headlineLarge?.copyWith(
color: ColorsManager.blackColor, color: ColorsManager.blackColor,
), ),
), ),
@ -92,7 +66,7 @@ class CommunityStructureHeader extends StatelessWidget {
Flexible( Flexible(
child: SelectableText( child: SelectableText(
selectedCommunity.name, selectedCommunity.name,
style: theme.textTheme.bodyLarge?.copyWith( style: context.textTheme.bodyLarge?.copyWith(
color: ColorsManager.blackColor, color: ColorsManager.blackColor,
), ),
maxLines: 1, maxLines: 1,
@ -116,39 +90,8 @@ class CommunityStructureHeader extends StatelessWidget {
), ),
), ),
const SizedBox(width: 8), const SizedBox(width: 8),
CommunityStructureHeaderActionButtons( CommunityStructureHeaderActionButtonsComposer(
onDelete: (space) => showDialog<void>( selectedCommunity: selectedCommunity,
context: context,
barrierDismissible: false,
builder: (_) => DeleteSpaceDialog(
space: space,
community: selectedCommunity,
onSuccess: () {
context.read<CommunitiesTreeSelectionBloc>().add(
SelectCommunityEvent(community: selectedCommunity),
);
},
),
),
onDuplicate: (space) {},
onEdit: (space) => SpaceDetailsDialogHelper.showEdit(
context,
spaceModel: selectedSpace!,
communityUuid: selectedCommunity.uuid,
onSuccess: (updatedSpaceDetails) {
final communitiesBloc = context.read<CommunitiesBloc>();
final updatedSpaces = _updateRecursive(
selectedCommunity.spaces,
updatedSpaceDetails,
);
final community = selectedCommunity.copyWith(
spaces: updatedSpaces,
);
communitiesBloc.add(CommunitiesUpdateCommunity(community));
},
),
selectedSpace: selectedSpace, selectedSpace: selectedSpace,
), ),
], ],

View File

@ -0,0 +1,69 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/space_management_v2/main_module/helpers/spaces_recursive_helper.dart';
import 'package:syncrow_web/pages/space_management_v2/main_module/widgets/community_structure_header_action_buttons.dart';
import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/models/community_model.dart';
import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/models/space_model.dart';
import 'package:syncrow_web/pages/space_management_v2/modules/communities/presentation/bloc/communities_bloc.dart';
import 'package:syncrow_web/pages/space_management_v2/modules/communities/presentation/communities_tree_selection_bloc/communities_tree_selection_bloc.dart';
import 'package:syncrow_web/pages/space_management_v2/modules/delete_space/presentation/widgets/delete_space_dialog.dart';
import 'package:syncrow_web/pages/space_management_v2/modules/space_details/presentation/helpers/space_details_dialog_helper.dart';
class CommunityStructureHeaderActionButtonsComposer extends StatelessWidget {
const CommunityStructureHeaderActionButtonsComposer({
required this.selectedCommunity,
required this.selectedSpace,
super.key,
});
final CommunityModel selectedCommunity;
final SpaceModel? selectedSpace;
@override
Widget build(BuildContext context) {
return CommunityStructureHeaderActionButtons(
onDelete: (space) => showDialog<void>(
context: context,
barrierDismissible: false,
builder: (_) => DeleteSpaceDialog(
space: space,
community: selectedCommunity,
onSuccess: () {
final updatedSpaces = SpacesRecursiveHelper.recusrivelyDelete(
selectedCommunity.spaces,
space.uuid,
);
final community = selectedCommunity.copyWith(
spaces: updatedSpaces,
);
context.read<CommunitiesBloc>().add(
CommunitiesUpdateCommunity(community),
);
context.read<CommunitiesTreeSelectionBloc>().add(
SelectCommunityEvent(community: selectedCommunity),
);
},
),
),
onDuplicate: (space) {},
onEdit: (space) => SpaceDetailsDialogHelper.showEdit(
context,
spaceModel: selectedSpace!,
communityUuid: selectedCommunity.uuid,
onSuccess: (updatedSpaceDetails) {
final communitiesBloc = context.read<CommunitiesBloc>();
final updatedSpaces = SpacesRecursiveHelper.recusrivelyUpdate(
selectedCommunity.spaces,
updatedSpaceDetails,
);
final community = selectedCommunity.copyWith(
spaces: updatedSpaces,
);
communitiesBloc.add(CommunitiesUpdateCommunity(community));
},
),
selectedSpace: selectedSpace,
);
}
}