Implement SpaceTreeDropdownBloc for improved state management in SpaceTreeDropdown; refactor dropdown logic and event handling.

This commit is contained in:
mohammad
2025-06-11 14:14:21 +03:00
parent d66921c615
commit fc86042af7
4 changed files with 137 additions and 85 deletions

View File

@ -5,6 +5,7 @@ import 'package:syncrow_web/pages/space_tree/bloc/space_tree_bloc.dart';
import 'package:syncrow_web/pages/space_tree/bloc/space_tree_state.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
import 'package:syncrow_web/utils/color_manager.dart';
import 'space_tree_dropdown_bloc.dart';
class SpaceTreeDropdown extends StatefulWidget {
final String? selectedSpaceId;
@ -21,18 +22,19 @@ class SpaceTreeDropdown extends StatefulWidget {
}
class _SpaceTreeDropdownState extends State<SpaceTreeDropdown> {
late String? _selectedSpaceId;
late SpaceTreeDropdownBloc _dropdownBloc;
final LayerLink _layerLink = LayerLink();
OverlayEntry? _overlayEntry;
@override
void initState() {
super.initState();
_selectedSpaceId = widget.selectedSpaceId;
_dropdownBloc = SpaceTreeDropdownBloc(widget.selectedSpaceId);
}
@override
void dispose() {
_dropdownBloc.close();
_removeOverlay();
super.dispose();
}
@ -44,87 +46,95 @@ class _SpaceTreeDropdownState extends State<SpaceTreeDropdown> {
@override
Widget build(BuildContext context) {
return BlocBuilder<SpaceTreeBloc, SpaceTreeState>(
builder: (context, state) {
final communities = state.searchQuery.isNotEmpty
? state.filteredCommunity
: state.communityList;
final selectedCommunity = _findCommunity(communities, _selectedSpaceId);
return BlocProvider.value(
value: _dropdownBloc,
child: BlocBuilder<SpaceTreeBloc, SpaceTreeState>(
builder: (context, spaceTreeState) {
final communities = spaceTreeState.searchQuery.isNotEmpty
? spaceTreeState.filteredCommunity
: spaceTreeState.communityList;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 10,
),
child: Text(
"Community",
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
fontWeight: FontWeight.w400,
fontSize: 13,
color: ColorsManager.blackColor,
),
),
),
CompositedTransformTarget(
link: _layerLink,
child: GestureDetector(
onTap: _toggleDropdown,
child: Container(
height: 46,
decoration: BoxDecoration(
border: Border.all(color: Colors.grey.shade300),
borderRadius: BorderRadius.circular(12),
),
margin: const EdgeInsets.symmetric(
horizontal: 10,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: Text(
selectedCommunity?.name ?? 'Please Select',
style: TextStyle(
color: selectedCommunity != null
? ColorsManager.blackColor
: ColorsManager.textGray,
overflow: TextOverflow.ellipsis,
return BlocBuilder<SpaceTreeDropdownBloc, SpaceTreeDropdownState>(
builder: (context, dropdownState) {
final selectedCommunity = _findCommunity(
communities,
dropdownState.selectedSpaceId,
);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: Text(
"Community",
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
fontWeight: FontWeight.w400,
fontSize: 13,
color: ColorsManager.blackColor,
),
),
),
Container(
decoration: BoxDecoration(
color: Colors.grey[200],
borderRadius: const BorderRadius.only(
topRight: Radius.circular(10),
bottomRight: Radius.circular(10),
),
),
height: 45,
width: 33,
child: const Icon(
Icons.keyboard_arrow_down,
color: ColorsManager.textGray,
),
),
],
),
),
),
),
),
],
);
},
CompositedTransformTarget(
link: _layerLink,
child: GestureDetector(
onTap: () => _toggleDropdown(context, communities),
child: Container(
height: 46,
decoration: BoxDecoration(
border: Border.all(color: Colors.grey.shade300),
borderRadius: BorderRadius.circular(12),
),
margin: const EdgeInsets.symmetric(horizontal: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Padding(
padding:
const EdgeInsets.symmetric(horizontal: 10),
child: Text(
selectedCommunity?.name ?? 'Please Select',
style: TextStyle(
color: selectedCommunity != null
? ColorsManager.blackColor
: ColorsManager.textGray,
overflow: TextOverflow.ellipsis,
fontWeight: FontWeight.w400,
fontSize: 13,
),
),
),
Container(
decoration: BoxDecoration(
color: Colors.grey[200],
borderRadius: const BorderRadius.only(
topRight: Radius.circular(10),
bottomRight: Radius.circular(10),
),
),
height: 45,
width: 33,
child: const Icon(
Icons.keyboard_arrow_down,
color: ColorsManager.textGray,
),
),
],
),
),
),
),
],
);
},
);
},
),
);
}
void _toggleDropdown() {
void _toggleDropdown(BuildContext context, List<CommunityModel> communities) {
if (_overlayEntry != null) {
_removeOverlay();
return;
@ -141,10 +151,10 @@ class _SpaceTreeDropdownState extends State<SpaceTreeDropdown> {
elevation: 8,
borderRadius: BorderRadius.circular(12),
child: DropdownMenuContent(
selectedSpaceId: _selectedSpaceId,
selectedSpaceId: _dropdownBloc.state.selectedSpaceId,
onChanged: (id) {
if (id != null && mounted) {
setState(() => _selectedSpaceId = id);
_dropdownBloc.add(SpaceTreeDropdownSelectEvent(id));
widget.onChanged?.call(id);
_removeOverlay();
}
@ -162,17 +172,10 @@ class _SpaceTreeDropdownState extends State<SpaceTreeDropdown> {
CommunityModel? _findCommunity(
List<CommunityModel> communities, String? communityId) {
if (communityId == null) return null;
try {
return communities.firstWhere((c) => c.uuid == communityId);
} catch (e) {
return CommunityModel(
uuid: '',
createdAt: DateTime.now(),
updatedAt: DateTime.now(),
name: '',
description: '',
spaces: []);
return null;
}
}
}

View File

@ -0,0 +1,27 @@
import 'package:flutter_bloc/flutter_bloc.dart';
part 'space_tree_dropdown_event.dart';
part 'space_tree_dropdown_state.dart';
class SpaceTreeDropdownBloc
extends Bloc<SpaceTreeDropdownEvent, SpaceTreeDropdownState> {
SpaceTreeDropdownBloc(String? initialId)
: super(SpaceTreeDropdownState(selectedSpaceId: initialId)) {
on<SpaceTreeDropdownSelectEvent>(_onSelect);
on<SpaceTreeDropdownResetEvent>(_onReset);
}
void _onSelect(
SpaceTreeDropdownSelectEvent event,
Emitter<SpaceTreeDropdownState> emit,
) {
emit(SpaceTreeDropdownState(selectedSpaceId: event.spaceId));
}
void _onReset(
SpaceTreeDropdownResetEvent event,
Emitter<SpaceTreeDropdownState> emit,
) {
emit(SpaceTreeDropdownState(selectedSpaceId: event.initialId));
}
}

View File

@ -0,0 +1,15 @@
part of 'space_tree_dropdown_bloc.dart';
abstract class SpaceTreeDropdownEvent {}
class SpaceTreeDropdownSelectEvent extends SpaceTreeDropdownEvent {
final String? spaceId;
SpaceTreeDropdownSelectEvent(this.spaceId);
}
class SpaceTreeDropdownResetEvent extends SpaceTreeDropdownEvent {
final String? initialId;
SpaceTreeDropdownResetEvent(this.initialId);
}

View File

@ -0,0 +1,7 @@
part of 'space_tree_dropdown_bloc.dart';
class SpaceTreeDropdownState {
final String? selectedSpaceId;
SpaceTreeDropdownState({this.selectedSpaceId});
}