mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-10 07:07:19 +00:00
Implemented PR notes by extracting widgets into their own classes.
This commit is contained in:
10
lib/common/widgets/app_loading_indicator.dart
Normal file
10
lib/common/widgets/app_loading_indicator.dart
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class AppLoadingIndicator extends StatelessWidget {
|
||||||
|
const AppLoadingIndicator({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return const Center(child: CircularProgressIndicator());
|
||||||
|
}
|
||||||
|
}
|
@ -19,12 +19,10 @@ class PaginatedDataModel<T> extends Equatable {
|
|||||||
|
|
||||||
factory PaginatedDataModel.fromJson(
|
factory PaginatedDataModel.fromJson(
|
||||||
Map<String, dynamic> json,
|
Map<String, dynamic> json,
|
||||||
T Function(Map<String, dynamic>) fromJsonT,
|
List<T> Function(List<dynamic>) fromJsonList,
|
||||||
) {
|
) {
|
||||||
return PaginatedDataModel<T>(
|
return PaginatedDataModel<T>(
|
||||||
data: (json['data'] as List<dynamic>? ?? [])
|
data: fromJsonList(json['data'] as List<dynamic>),
|
||||||
.map((e) => fromJsonT(e as Map<String, dynamic>))
|
|
||||||
.toList(),
|
|
||||||
page: json['page'] as int? ?? 1,
|
page: json['page'] as int? ?? 1,
|
||||||
size: json['size'] as int? ?? 25,
|
size: json['size'] as int? ?? 25,
|
||||||
hasNext: json['hasNext'] as bool? ?? false,
|
hasNext: json['hasNext'] as bool? ?? false,
|
||||||
|
@ -28,10 +28,10 @@ class RemoteCommunitiesService implements CommunitiesService {
|
|||||||
if (param.search.isNotEmpty && param.search != 'null')
|
if (param.search.isNotEmpty && param.search != 'null')
|
||||||
'search': param.search,
|
'search': param.search,
|
||||||
},
|
},
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) => CommunitiesPaginationModel.fromJson(
|
||||||
final data = json as Map<String, dynamic>;
|
json as Map<String, dynamic>,
|
||||||
return CommunitiesPaginationModel.fromJson(data, CommunityModel.fromJson);
|
CommunityModel.fromJsonList,
|
||||||
},
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
|
@ -33,6 +33,11 @@ class CommunityModel extends Equatable {
|
|||||||
.toList(),
|
.toList(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
static List<CommunityModel> fromJsonList(List<dynamic> json) {
|
||||||
|
return json
|
||||||
|
.map((e) => CommunityModel.fromJson(e as Map<String, dynamic>))
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object?> get props => [uuid, name, spaces];
|
List<Object?> get props => [uuid, name, spaces];
|
||||||
|
@ -0,0 +1,38 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/params/load_communities_param.dart';
|
||||||
|
import 'package:syncrow_web/pages/space_management_v2/modules/communities/presentation/bloc/communities_bloc.dart';
|
||||||
|
|
||||||
|
class CommunitiesTreeFailureWidget extends StatelessWidget {
|
||||||
|
const CommunitiesTreeFailureWidget({super.key, this.errorMessage});
|
||||||
|
|
||||||
|
final String? errorMessage;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Expanded(
|
||||||
|
child: Center(
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
errorMessage ?? 'Something went wrong',
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () => context.read<CommunitiesBloc>().add(
|
||||||
|
LoadCommunities(
|
||||||
|
LoadCommunitiesParam(
|
||||||
|
search: context.read<CommunitiesBloc>().state.searchQuery,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: const Text('Retry'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class EmptyCommunitiesTreeSearchResultWidget extends StatelessWidget {
|
||||||
|
const EmptyCommunitiesTreeSearchResultWidget({
|
||||||
|
required this.searchQuery,
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
final String searchQuery;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Center(
|
||||||
|
child: Text(
|
||||||
|
searchQuery.isEmpty
|
||||||
|
? 'No communities found'
|
||||||
|
: 'No communities found for "$searchQuery"',
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,16 +1,14 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_web/common/widgets/app_loading_indicator.dart';
|
||||||
import 'package:syncrow_web/common/widgets/search_bar.dart';
|
import 'package:syncrow_web/common/widgets/search_bar.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/domain/params/load_communities_param.dart';
|
import 'package:syncrow_web/pages/space_management_v2/modules/communities/domain/params/load_communities_param.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/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/widgets/communities_tree_failure_widget.dart';
|
||||||
import 'package:syncrow_web/pages/space_management_v2/modules/communities/presentation/widgets/community_tile.dart';
|
import 'package:syncrow_web/pages/space_management_v2/modules/communities/presentation/widgets/empty_communities_tree_search_result_widget.dart';
|
||||||
|
import 'package:syncrow_web/pages/space_management_v2/modules/communities/presentation/widgets/space_management_communities_tree_community_tile.dart';
|
||||||
import 'package:syncrow_web/pages/space_management_v2/modules/communities/presentation/widgets/space_management_sidebar_communities_list.dart';
|
import 'package:syncrow_web/pages/space_management_v2/modules/communities/presentation/widgets/space_management_sidebar_communities_list.dart';
|
||||||
import 'package:syncrow_web/pages/space_management_v2/modules/communities/presentation/widgets/space_management_sidebar_header.dart';
|
import 'package:syncrow_web/pages/space_management_v2/modules/communities/presentation/widgets/space_management_sidebar_header.dart';
|
||||||
import 'package:syncrow_web/pages/space_management_v2/modules/communities/presentation/widgets/space_tile.dart';
|
|
||||||
import 'package:syncrow_web/pages/space_management_v2/modules/create_community/presentation/create_community_dialog.dart';
|
|
||||||
import 'package:syncrow_web/utils/style.dart';
|
import 'package:syncrow_web/utils/style.dart';
|
||||||
|
|
||||||
class SpaceManagementCommunitiesTree extends StatefulWidget {
|
class SpaceManagementCommunitiesTree extends StatefulWidget {
|
||||||
@ -31,16 +29,6 @@ class _SpaceManagementCommunitiesTreeState
|
|||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _isSpaceOrChildSelected(BuildContext context, SpaceModel space) {
|
|
||||||
final selectedSpace =
|
|
||||||
context.read<CommunitiesTreeSelectionBloc>().state.selectedSpace;
|
|
||||||
final isSpaceSelected = selectedSpace?.uuid == space.uuid;
|
|
||||||
final anySubSpaceIsSelected = space.children.any(
|
|
||||||
(child) => _isSpaceOrChildSelected(context, child),
|
|
||||||
);
|
|
||||||
return isSpaceSelected || anySubSpaceIsSelected;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _onSearchChanged(String searchQuery) {
|
void _onSearchChanged(String searchQuery) {
|
||||||
context
|
context
|
||||||
.read<CommunitiesBloc>()
|
.read<CommunitiesBloc>()
|
||||||
@ -51,67 +39,32 @@ class _SpaceManagementCommunitiesTreeState
|
|||||||
context.read<CommunitiesBloc>().add(const LoadMoreCommunities());
|
context.read<CommunitiesBloc>().add(const LoadMoreCommunities());
|
||||||
}
|
}
|
||||||
|
|
||||||
static const _width = 300.0;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocBuilder<CommunitiesBloc, CommunitiesState>(
|
return BlocBuilder<CommunitiesBloc, CommunitiesState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) => Container(
|
||||||
return Container(
|
width: 320,
|
||||||
width: _width,
|
decoration: subSectionContainerDecoration,
|
||||||
decoration: subSectionContainerDecoration,
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
SpaceManagementSidebarHeader(
|
|
||||||
onAddCommunity: () => _onAddCommunity(context),
|
|
||||||
),
|
|
||||||
CustomSearchBar(
|
|
||||||
onSearchChanged: _onSearchChanged,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
switch (state.status) {
|
|
||||||
CommunitiesStatus.initial =>
|
|
||||||
const Center(child: CircularProgressIndicator()),
|
|
||||||
CommunitiesStatus.loading => state.communities.isEmpty
|
|
||||||
? const Center(child: CircularProgressIndicator())
|
|
||||||
: _buildCommunitiesTree(context, state),
|
|
||||||
CommunitiesStatus.success => _buildCommunitiesTree(context, state),
|
|
||||||
CommunitiesStatus.failure => _buildErrorState(context, state),
|
|
||||||
},
|
|
||||||
Visibility(
|
|
||||||
visible: state.isLoadingMore,
|
|
||||||
child: const Padding(
|
|
||||||
padding: EdgeInsets.all(8.0),
|
|
||||||
child: Center(child: CircularProgressIndicator()),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildErrorState(BuildContext context, CommunitiesState state) {
|
|
||||||
return Expanded(
|
|
||||||
child: Center(
|
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
children: [
|
||||||
Text(
|
const SpaceManagementSidebarHeader(),
|
||||||
state.errorMessage ?? 'Something went wrong',
|
CustomSearchBar(
|
||||||
textAlign: TextAlign.center,
|
onSearchChanged: _onSearchChanged,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
ElevatedButton(
|
switch (state.status) {
|
||||||
onPressed: () {
|
CommunitiesStatus.initial => const AppLoadingIndicator(),
|
||||||
context.read<CommunitiesBloc>().add(
|
CommunitiesStatus.loading => state.communities.isEmpty
|
||||||
LoadCommunities(LoadCommunitiesParam(
|
? const AppLoadingIndicator()
|
||||||
search: state.searchQuery,
|
: _buildCommunitiesTree(context, state),
|
||||||
)),
|
CommunitiesStatus.success => _buildCommunitiesTree(context, state),
|
||||||
);
|
CommunitiesStatus.failure => CommunitiesTreeFailureWidget(
|
||||||
},
|
errorMessage: state.errorMessage,
|
||||||
child: const Text('Retry'),
|
),
|
||||||
|
},
|
||||||
|
Visibility(
|
||||||
|
visible: state.isLoadingMore,
|
||||||
|
child: const AppLoadingIndicator(),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -123,132 +76,37 @@ class _SpaceManagementCommunitiesTreeState
|
|||||||
BuildContext context,
|
BuildContext context,
|
||||||
CommunitiesState state,
|
CommunitiesState state,
|
||||||
) {
|
) {
|
||||||
if (state.communities.isEmpty && state.status == CommunitiesStatus.success) {
|
final communitiesIsEmpty = state.communities.isEmpty;
|
||||||
return Expanded(
|
final statusIsSuccess = state.status == CommunitiesStatus.success;
|
||||||
child: Center(
|
|
||||||
child: Text(
|
|
||||||
state.searchQuery.isEmpty
|
|
||||||
? 'No communities found'
|
|
||||||
: 'No communities found for "${state.searchQuery}"',
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Expanded(
|
return Expanded(
|
||||||
child: Stack(
|
child: Visibility(
|
||||||
children: [
|
visible: statusIsSuccess && communitiesIsEmpty,
|
||||||
SpaceManagementSidebarCommunitiesList(
|
replacement: Stack(
|
||||||
communities: state.communities,
|
children: [
|
||||||
onLoadMore: state.hasNext ? _onLoadMore : null,
|
SpaceManagementSidebarCommunitiesList(
|
||||||
isLoadingMore: state.isLoadingMore,
|
communities: state.communities,
|
||||||
hasNext: state.hasNext,
|
onLoadMore: state.hasNext ? _onLoadMore : null,
|
||||||
itemBuilder: (context, index) {
|
isLoadingMore: state.isLoadingMore,
|
||||||
return _buildCommunityTile(context, state.communities[index]);
|
hasNext: state.hasNext,
|
||||||
},
|
itemBuilder: (context, index) {
|
||||||
),
|
return SpaceManagementCommunitiesTreeCommunityTile(
|
||||||
if (state.status == CommunitiesStatus.loading &&
|
community: state.communities[index],
|
||||||
state.communities.isNotEmpty)
|
);
|
||||||
ColoredBox(
|
},
|
||||||
color: Colors.white.withValues(alpha: 0.7),
|
|
||||||
child: const Center(child: CircularProgressIndicator()),
|
|
||||||
),
|
),
|
||||||
],
|
if (state.status == CommunitiesStatus.loading &&
|
||||||
),
|
state.communities.isNotEmpty)
|
||||||
);
|
ColoredBox(
|
||||||
}
|
color: Colors.white.withValues(alpha: 0.7),
|
||||||
|
child: const AppLoadingIndicator(),
|
||||||
Widget _buildCommunityTile(BuildContext context, CommunityModel community) {
|
|
||||||
final spaces = community.spaces
|
|
||||||
.map((space) => _buildSpaceTile(
|
|
||||||
space: space,
|
|
||||||
community: community,
|
|
||||||
context: context,
|
|
||||||
))
|
|
||||||
.toList();
|
|
||||||
return CommunityTile(
|
|
||||||
title: community.name,
|
|
||||||
key: ValueKey(community.uuid),
|
|
||||||
isSelected: context
|
|
||||||
.watch<CommunitiesTreeSelectionBloc>()
|
|
||||||
.state
|
|
||||||
.selectedCommunity
|
|
||||||
?.uuid ==
|
|
||||||
community.uuid,
|
|
||||||
isExpanded: false,
|
|
||||||
onItemSelected: () {
|
|
||||||
context.read<CommunitiesTreeSelectionBloc>().add(
|
|
||||||
SelectCommunityEvent(community: community),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
onExpansionChanged: (title, expanded) {},
|
|
||||||
children: spaces,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildSpaceTile({
|
|
||||||
required SpaceModel space,
|
|
||||||
required CommunityModel community,
|
|
||||||
required BuildContext context,
|
|
||||||
}) {
|
|
||||||
final spaceIsExpanded = _isSpaceOrChildSelected(context, space);
|
|
||||||
final isSelected =
|
|
||||||
context.watch<CommunitiesTreeSelectionBloc>().state.selectedSpace?.uuid ==
|
|
||||||
space.uuid;
|
|
||||||
return Padding(
|
|
||||||
padding: const EdgeInsetsDirectional.only(start: 16.0),
|
|
||||||
child: SpaceTile(
|
|
||||||
title: space.spaceName,
|
|
||||||
key: ValueKey(space.uuid),
|
|
||||||
isSelected: isSelected,
|
|
||||||
initiallyExpanded: spaceIsExpanded,
|
|
||||||
onExpansionChanged: (expanded) {},
|
|
||||||
onItemSelected: () => context.read<CommunitiesTreeSelectionBloc>().add(
|
|
||||||
SelectSpaceEvent(space: space),
|
|
||||||
),
|
|
||||||
children: space.children
|
|
||||||
.map(
|
|
||||||
(childSpace) => _buildSpaceTile(
|
|
||||||
space: childSpace,
|
|
||||||
community: community,
|
|
||||||
context: context,
|
|
||||||
),
|
),
|
||||||
)
|
],
|
||||||
.toList(),
|
),
|
||||||
|
child: EmptyCommunitiesTreeSearchResultWidget(
|
||||||
|
searchQuery: state.searchQuery,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onAddCommunity(BuildContext context) {
|
|
||||||
context
|
|
||||||
.read<CommunitiesTreeSelectionBloc>()
|
|
||||||
.state
|
|
||||||
.selectedCommunity
|
|
||||||
?.uuid
|
|
||||||
.isNotEmpty ??
|
|
||||||
false
|
|
||||||
? _clearSelection(context)
|
|
||||||
: _showCreateCommunityDialog(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _clearSelection(BuildContext context) =>
|
|
||||||
context.read<CommunitiesTreeSelectionBloc>().add(
|
|
||||||
const ClearCommunitiesTreeSelectionEvent(),
|
|
||||||
);
|
|
||||||
|
|
||||||
void _showCreateCommunityDialog(BuildContext context) => showDialog<void>(
|
|
||||||
context: context,
|
|
||||||
builder: (_) => CreateCommunityDialog(
|
|
||||||
title: const Text('Community Name'),
|
|
||||||
onCreateCommunity: (community) {
|
|
||||||
context.read<CommunitiesBloc>().add(
|
|
||||||
InsertCommunity(community),
|
|
||||||
);
|
|
||||||
context.read<CommunitiesTreeSelectionBloc>().add(
|
|
||||||
SelectCommunityEvent(community: community),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,45 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.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/presentation/communities_tree_selection_bloc/communities_tree_selection_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/space_management_v2/modules/communities/presentation/widgets/community_tile.dart';
|
||||||
|
import 'package:syncrow_web/pages/space_management_v2/modules/communities/presentation/widgets/space_management_communities_tree_space_tile.dart';
|
||||||
|
|
||||||
|
class SpaceManagementCommunitiesTreeCommunityTile extends StatelessWidget {
|
||||||
|
const SpaceManagementCommunitiesTreeCommunityTile({
|
||||||
|
required this.community,
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
final CommunityModel community;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final spaces = community.spaces
|
||||||
|
.map(
|
||||||
|
(space) => SpaceManagementCommunitiesTreeSpaceTile(
|
||||||
|
space: space,
|
||||||
|
community: community,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList();
|
||||||
|
return CommunityTile(
|
||||||
|
title: community.name,
|
||||||
|
key: ValueKey(community.uuid),
|
||||||
|
isSelected: context
|
||||||
|
.watch<CommunitiesTreeSelectionBloc>()
|
||||||
|
.state
|
||||||
|
.selectedCommunity
|
||||||
|
?.uuid ==
|
||||||
|
community.uuid,
|
||||||
|
isExpanded: false,
|
||||||
|
onItemSelected: () {
|
||||||
|
context.read<CommunitiesTreeSelectionBloc>().add(
|
||||||
|
SelectCommunityEvent(community: community),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
onExpansionChanged: (title, expanded) {},
|
||||||
|
children: spaces,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.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/communities_tree_selection_bloc/communities_tree_selection_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/space_management_v2/modules/communities/presentation/widgets/space_tile.dart';
|
||||||
|
|
||||||
|
class SpaceManagementCommunitiesTreeSpaceTile extends StatelessWidget {
|
||||||
|
const SpaceManagementCommunitiesTreeSpaceTile({
|
||||||
|
required this.space,
|
||||||
|
required this.community,
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
final SpaceModel space;
|
||||||
|
final CommunityModel community;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final spaceIsExpanded = _isSpaceOrChildSelected(context, space);
|
||||||
|
final isSelected =
|
||||||
|
context.watch<CommunitiesTreeSelectionBloc>().state.selectedSpace?.uuid ==
|
||||||
|
space.uuid;
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsetsDirectional.only(start: 16.0),
|
||||||
|
child: SpaceTile(
|
||||||
|
title: space.spaceName,
|
||||||
|
key: ValueKey(space.uuid),
|
||||||
|
isSelected: isSelected,
|
||||||
|
initiallyExpanded: spaceIsExpanded,
|
||||||
|
onExpansionChanged: (expanded) {},
|
||||||
|
onItemSelected: () => context.read<CommunitiesTreeSelectionBloc>().add(
|
||||||
|
SelectSpaceEvent(space: space),
|
||||||
|
),
|
||||||
|
children: space.children
|
||||||
|
.map(
|
||||||
|
(childSpace) => SpaceManagementCommunitiesTreeSpaceTile(
|
||||||
|
space: childSpace,
|
||||||
|
community: community,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _isSpaceOrChildSelected(BuildContext context, SpaceModel space) {
|
||||||
|
final selectedSpace =
|
||||||
|
context.read<CommunitiesTreeSelectionBloc>().state.selectedSpace;
|
||||||
|
final isSpaceSelected = selectedSpace?.uuid == space.uuid;
|
||||||
|
final anySubSpaceIsSelected = space.children.any(
|
||||||
|
(child) => _isSpaceOrChildSelected(context, child),
|
||||||
|
);
|
||||||
|
return isSpaceSelected || anySubSpaceIsSelected;
|
||||||
|
}
|
||||||
|
}
|
@ -1,16 +1,15 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.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/widgets/space_management_sidebar_add_community_button.dart';
|
import 'package:syncrow_web/pages/space_management_v2/modules/communities/presentation/widgets/space_management_sidebar_add_community_button.dart';
|
||||||
|
import 'package:syncrow_web/pages/space_management_v2/modules/create_community/presentation/create_community_dialog.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
||||||
import 'package:syncrow_web/utils/style.dart';
|
import 'package:syncrow_web/utils/style.dart';
|
||||||
|
|
||||||
class SpaceManagementSidebarHeader extends StatelessWidget {
|
class SpaceManagementSidebarHeader extends StatelessWidget {
|
||||||
const SpaceManagementSidebarHeader({
|
const SpaceManagementSidebarHeader({super.key});
|
||||||
required this.onAddCommunity,
|
|
||||||
super.key,
|
|
||||||
});
|
|
||||||
|
|
||||||
final void Function() onAddCommunity;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -27,10 +26,43 @@ class SpaceManagementSidebarHeader extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
SpaceManagementSidebarAddCommunityButton(
|
SpaceManagementSidebarAddCommunityButton(
|
||||||
onTap: onAddCommunity,
|
onTap: () => _onAddCommunity(context),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _onAddCommunity(BuildContext context) {
|
||||||
|
final bloc = context.read<CommunitiesTreeSelectionBloc>();
|
||||||
|
final selectedCommunity = bloc.state.selectedCommunity;
|
||||||
|
final isSelected = selectedCommunity?.uuid.isNotEmpty ?? false;
|
||||||
|
|
||||||
|
if (isSelected) {
|
||||||
|
_clearSelection(context);
|
||||||
|
} else {
|
||||||
|
_showCreateCommunityDialog(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _clearSelection(BuildContext context) {
|
||||||
|
context.read<CommunitiesTreeSelectionBloc>().add(
|
||||||
|
const ClearCommunitiesTreeSelectionEvent(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _showCreateCommunityDialog(BuildContext context) => showDialog<void>(
|
||||||
|
context: context,
|
||||||
|
builder: (_) => CreateCommunityDialog(
|
||||||
|
title: const Text('Community Name'),
|
||||||
|
onCreateCommunity: (community) {
|
||||||
|
context.read<CommunitiesBloc>().add(
|
||||||
|
InsertCommunity(community),
|
||||||
|
);
|
||||||
|
context.read<CommunitiesTreeSelectionBloc>().add(
|
||||||
|
SelectCommunityEvent(community: community),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,7 @@ class _CreateCommunityDialogWidgetState extends State<CreateCommunityDialogWidge
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Row _buildActionButtons(BuildContext context) {
|
Widget _buildActionButtons(BuildContext context) {
|
||||||
return Row(
|
return Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
|
Reference in New Issue
Block a user