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/space_tree/bloc/space_tree_state.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart'; import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
import 'space_tree_dropdown_bloc.dart';
class SpaceTreeDropdown extends StatefulWidget { class SpaceTreeDropdown extends StatefulWidget {
final String? selectedSpaceId; final String? selectedSpaceId;
@ -21,18 +22,19 @@ class SpaceTreeDropdown extends StatefulWidget {
} }
class _SpaceTreeDropdownState extends State<SpaceTreeDropdown> { class _SpaceTreeDropdownState extends State<SpaceTreeDropdown> {
late String? _selectedSpaceId; late SpaceTreeDropdownBloc _dropdownBloc;
final LayerLink _layerLink = LayerLink(); final LayerLink _layerLink = LayerLink();
OverlayEntry? _overlayEntry; OverlayEntry? _overlayEntry;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_selectedSpaceId = widget.selectedSpaceId; _dropdownBloc = SpaceTreeDropdownBloc(widget.selectedSpaceId);
} }
@override @override
void dispose() { void dispose() {
_dropdownBloc.close();
_removeOverlay(); _removeOverlay();
super.dispose(); super.dispose();
} }
@ -44,87 +46,95 @@ class _SpaceTreeDropdownState extends State<SpaceTreeDropdown> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocBuilder<SpaceTreeBloc, SpaceTreeState>( return BlocProvider.value(
builder: (context, state) { value: _dropdownBloc,
final communities = state.searchQuery.isNotEmpty child: BlocBuilder<SpaceTreeBloc, SpaceTreeState>(
? state.filteredCommunity builder: (context, spaceTreeState) {
: state.communityList; final communities = spaceTreeState.searchQuery.isNotEmpty
final selectedCommunity = _findCommunity(communities, _selectedSpaceId); ? spaceTreeState.filteredCommunity
: spaceTreeState.communityList;
return Column( return BlocBuilder<SpaceTreeDropdownBloc, SpaceTreeDropdownState>(
crossAxisAlignment: CrossAxisAlignment.start, builder: (context, dropdownState) {
mainAxisAlignment: MainAxisAlignment.start, final selectedCommunity = _findCommunity(
children: [ communities,
Padding( dropdownState.selectedSpaceId,
padding: const EdgeInsets.symmetric( );
horizontal: 10,
), return Column(
child: Text( crossAxisAlignment: CrossAxisAlignment.start,
"Community", mainAxisAlignment: MainAxisAlignment.start,
style: Theme.of(context).textTheme.bodyMedium!.copyWith( children: [
fontWeight: FontWeight.w400, Padding(
fontSize: 13, padding: const EdgeInsets.symmetric(horizontal: 10),
color: ColorsManager.blackColor, child: Text(
), "Community",
), style: Theme.of(context).textTheme.bodyMedium!.copyWith(
),
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,
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
fontSize: 13, 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) { if (_overlayEntry != null) {
_removeOverlay(); _removeOverlay();
return; return;
@ -141,10 +151,10 @@ class _SpaceTreeDropdownState extends State<SpaceTreeDropdown> {
elevation: 8, elevation: 8,
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
child: DropdownMenuContent( child: DropdownMenuContent(
selectedSpaceId: _selectedSpaceId, selectedSpaceId: _dropdownBloc.state.selectedSpaceId,
onChanged: (id) { onChanged: (id) {
if (id != null && mounted) { if (id != null && mounted) {
setState(() => _selectedSpaceId = id); _dropdownBloc.add(SpaceTreeDropdownSelectEvent(id));
widget.onChanged?.call(id); widget.onChanged?.call(id);
_removeOverlay(); _removeOverlay();
} }
@ -162,17 +172,10 @@ class _SpaceTreeDropdownState extends State<SpaceTreeDropdown> {
CommunityModel? _findCommunity( CommunityModel? _findCommunity(
List<CommunityModel> communities, String? communityId) { List<CommunityModel> communities, String? communityId) {
if (communityId == null) return null; if (communityId == null) return null;
try { try {
return communities.firstWhere((c) => c.uuid == communityId); return communities.firstWhere((c) => c.uuid == communityId);
} catch (e) { } catch (e) {
return CommunityModel( return null;
uuid: '',
createdAt: DateTime.now(),
updatedAt: DateTime.now(),
name: '',
description: '',
spaces: []);
} }
} }
} }

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});
}