import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_web/pages/routines/create_new_routines/dropdown_menu_content.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 StatelessWidget { final String? selectedSpaceId; final Function(String?)? onChanged; const SpaceTreeDropdown({ super.key, this.selectedSpaceId, this.onChanged, }); @override Widget build(BuildContext context) { return BlocProvider( create: (context) { final bloc = SpaceTreeDropdownBloc(selectedSpaceId); bloc.add(FetchSpacesEvent()); return bloc; }, child: _DropdownContent(onChanged: onChanged), ); } } class _DropdownContent extends StatefulWidget { final Function(String?)? onChanged; const _DropdownContent({this.onChanged}); @override State<_DropdownContent> createState() => _DropdownContentState(); } class _DropdownContentState extends State<_DropdownContent> { final LayerLink _layerLink = LayerLink(); OverlayEntry? _overlayEntry; @override void dispose() { _removeOverlay(); super.dispose(); } void _removeOverlay() { _overlayEntry?.remove(); _overlayEntry = null; } @override Widget build(BuildContext context) { 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(context), child: BlocBuilder( builder: (context, state) { return _buildDropdownTrigger(state); }, ), ), ), ], ); } Widget _buildDropdownTrigger(SpaceTreeDropdownState state) { if (state.status == SpaceTreeDropdownStatus.loading) { return Container( height: 46, decoration: BoxDecoration( border: Border.all(color: Colors.grey.shade300), borderRadius: BorderRadius.circular(12), ), margin: const EdgeInsets.symmetric(horizontal: 10), child: const Center(child: CircularProgressIndicator()), ); } if (state.status == SpaceTreeDropdownStatus.failure) { return Container( height: 46, decoration: BoxDecoration( border: Border.all(color: Colors.grey.shade300), borderRadius: BorderRadius.circular(12), ), margin: const EdgeInsets.symmetric(horizontal: 10), child: Center( child: Text( 'Error: ${state.errorMessage}', style: const TextStyle(color: Colors.red), ), ), ); } final selectedCommunity = _findCommunity(state, state.selectedSpaceId); return 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(BuildContext context) { if (_overlayEntry != null) { _removeOverlay(); return; } final bloc = context.read(); _overlayEntry = OverlayEntry( builder: (context) => Positioned( width: 300, child: CompositedTransformFollower( link: _layerLink, showWhenUnlinked: false, offset: const Offset(0, 48), child: Material( color: ColorsManager.whiteColors, elevation: 8, borderRadius: BorderRadius.circular(12), child: BlocProvider.value( value: bloc, child: DropdownMenuContent( selectedSpaceId: bloc.state.selectedSpaceId, onChanged: (id) { if (id != null && mounted) { bloc.add(SpaceTreeDropdownSelectEvent(id)); widget.onChanged?.call(id); _removeOverlay(); } }, onClose: _removeOverlay, ), ), ), ), ), ); Overlay.of(context).insert(_overlayEntry!); } CommunityModel? _findCommunity( SpaceTreeDropdownState state, String? communityId) { if (communityId == null) return null; try { return state.filteredCommunities.firstWhere((c) => c.uuid == communityId); } catch (_) {} try { return state.communities.firstWhere((c) => c.uuid == communityId); } catch (e) { return null; } } }