diff --git a/lib/pages/routines/bloc/create_routine_bloc/create_routine_bloc.dart b/lib/pages/routines/bloc/create_routine_bloc/create_routine_bloc.dart index 5a8e5590..b472d034 100644 --- a/lib/pages/routines/bloc/create_routine_bloc/create_routine_bloc.dart +++ b/lib/pages/routines/bloc/create_routine_bloc/create_routine_bloc.dart @@ -2,6 +2,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_web/pages/common/bloc/project_manager.dart'; import 'package:syncrow_web/pages/routines/bloc/create_routine_bloc/create_routine_event.dart'; import 'package:syncrow_web/pages/routines/bloc/create_routine_bloc/create_routine_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/space_model.dart'; import 'package:syncrow_web/services/space_mana_api.dart'; @@ -10,11 +11,12 @@ class CreateRoutineBloc extends Bloc { on(_fetchSpaceOnlyWithDevices); on(saveSpaceIdCommunityId); on(resetSelected); + on(_fetchCommunity); } String selectedSpaceId = ''; String selectedCommunityId = ''; - + List communities = []; List spacesOnlyWithDevices = []; Future _fetchSpaceOnlyWithDevices( @@ -30,7 +32,7 @@ class CreateRoutineBloc extends Bloc { emit(SpaceWithDeviceLoadedState(spacesOnlyWithDevices)); } catch (e) { - emit(SpaceTreeErrorState('Error loading communities and spaces: $e')); + emit(SpaceTreeErrorState('Error loading spaces: $e')); } } @@ -48,4 +50,18 @@ class CreateRoutineBloc extends Bloc { selectedCommunityId = ''; emit(const ResetSelectedState()); } + + Future _fetchCommunity( + FetchCommunityEvent event, Emitter emit) async { + emit(const CommunitiesLoadingState()); + + try { + final projectUuid = await ProjectManager.getProjectUUID() ?? ''; + communities = + await CommunitySpaceManagementApi().fetchCommunities(projectUuid); + emit(const CommunityLoadedState()); + } catch (e) { + emit(SpaceTreeErrorState('Error loading communities $e')); + } + } } diff --git a/lib/pages/routines/bloc/create_routine_bloc/create_routine_event.dart b/lib/pages/routines/bloc/create_routine_bloc/create_routine_event.dart index 24e620c0..ba901497 100644 --- a/lib/pages/routines/bloc/create_routine_bloc/create_routine_event.dart +++ b/lib/pages/routines/bloc/create_routine_bloc/create_routine_event.dart @@ -41,3 +41,11 @@ class ResetSelectedEvent extends CreateRoutineEvent { @override List get props => []; } + + +class FetchCommunityEvent extends CreateRoutineEvent { + const FetchCommunityEvent(); + + @override + List get props => []; +} \ No newline at end of file diff --git a/lib/pages/routines/bloc/create_routine_bloc/create_routine_state.dart b/lib/pages/routines/bloc/create_routine_bloc/create_routine_state.dart index 4911304b..5ebc20f7 100644 --- a/lib/pages/routines/bloc/create_routine_bloc/create_routine_state.dart +++ b/lib/pages/routines/bloc/create_routine_bloc/create_routine_state.dart @@ -44,3 +44,10 @@ class ResetSelectedState extends CreateRoutineState { const ResetSelectedState(); } +class CommunityLoadedState extends CreateRoutineState { + const CommunityLoadedState(); +} + +class CommunitiesLoadingState extends CreateRoutineState { + const CommunitiesLoadingState(); +} \ No newline at end of file diff --git a/lib/pages/routines/create_new_routines/commu_dropdown.dart b/lib/pages/routines/create_new_routines/commu_dropdown.dart index 32ee7219..5b96e977 100644 --- a/lib/pages/routines/create_new_routines/commu_dropdown.dart +++ b/lib/pages/routines/create_new_routines/commu_dropdown.dart @@ -1,12 +1,11 @@ import 'package:dropdown_button2/dropdown_button2.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -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'; class CommunityDropdown extends StatelessWidget { final String? selectedValue; + final List communities; final Function(String?) onChanged; final TextEditingController _searchController = TextEditingController(); @@ -14,6 +13,7 @@ class CommunityDropdown extends StatelessWidget { Key? key, required this.selectedValue, required this.onChanged, + required this.communities, }) : super(key: key); @override @@ -32,123 +32,123 @@ class CommunityDropdown extends StatelessWidget { ), ), const SizedBox(height: 8), - BlocBuilder( - builder: (context, state) { - return SizedBox( - child: Container( + SizedBox( + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + ), + child: DropdownButton2( + underline: const SizedBox(), + value: selectedValue, + items: communities.map((community) { + return DropdownMenuItem( + value: community.uuid, + child: Text( + ' ${community.name}', + overflow: TextOverflow.ellipsis, + maxLines: 1, + ), + ); + }).toList(), + onChanged: onChanged, + style: const TextStyle(color: Colors.black), + hint: Padding( + padding: const EdgeInsets.only(left: 10), + child: Text( + " Please Select", + style: Theme.of(context).textTheme.bodySmall!.copyWith( + color: ColorsManager.textGray, + ), + ), + ), + customButton: Container( + height: 45, + decoration: BoxDecoration( + border: Border.all(color: ColorsManager.textGray, width: 1.0), + borderRadius: BorderRadius.circular(10), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + flex: 5, + child: Text( + selectedValue != null + ? " ${communities.firstWhere((element) => element.uuid == selectedValue).name}" + : ' Please Select', + style: Theme.of(context).textTheme.bodySmall!.copyWith( + color: selectedValue != null + ? Colors.black + : ColorsManager.textGray, + ), + overflow: TextOverflow.ellipsis, + ), + ), + Expanded( + child: Container( + decoration: BoxDecoration( + color: Colors.grey[100], + borderRadius: const BorderRadius.only( + topRight: Radius.circular(10), + bottomRight: Radius.circular(10), + ), + ), + height: 45, + child: const Icon( + Icons.keyboard_arrow_down, + color: ColorsManager.textGray, + ), + ), + ), + ], + ), + ), + dropdownStyleData: DropdownStyleData( + maxHeight: MediaQuery.of(context).size.height * 0.4, decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), ), - child: DropdownButton2( - underline: SizedBox(), - value: selectedValue, - items: state.communityList.map((community) { - return DropdownMenuItem( - value: community.uuid, - child: Text( - ' ${community.name}', - overflow: TextOverflow.ellipsis, - maxLines: 1, + ), + dropdownSearchData: DropdownSearchData( + searchController: _searchController, + searchInnerWidgetHeight: 50, + searchInnerWidget: Container( + height: 50, + padding: + const EdgeInsets.symmetric(horizontal: 8, vertical: 4), + child: TextFormField( + style: const TextStyle(color: Colors.black), + controller: _searchController, + decoration: InputDecoration( + isDense: true, + contentPadding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 12, ), - ); - }).toList(), - onChanged: onChanged, - style: TextStyle(color: Colors.black), - hint: Padding( - padding: EdgeInsets.only(left: 10), - child: Text( - " Please Select", - style: Theme.of(context).textTheme.bodySmall!.copyWith( - color: ColorsManager.textGray, - ), - ), - ), - customButton: Container( - height: 45, - decoration: BoxDecoration( - border: Border.all(color: ColorsManager.textGray, width: 1.0), - borderRadius: BorderRadius.circular(10), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - flex: 5, - child: Text( - selectedValue != null - ? " ${state.communityList.firstWhere((element) => element.uuid == selectedValue).name}" - : ' Please Select', - style: Theme.of(context).textTheme.bodySmall!.copyWith( - color: - selectedValue != null ? Colors.black : ColorsManager.textGray, - ), - overflow: TextOverflow.ellipsis, - ), - ), - Expanded( - child: Container( - decoration: BoxDecoration( - color: Colors.grey[100], - borderRadius: const BorderRadius.only( - topRight: Radius.circular(10), - bottomRight: Radius.circular(10), - ), - ), - height: 45, - child: const Icon( - Icons.keyboard_arrow_down, - color: ColorsManager.textGray, - ), - ), - ), - ], - ), - ), - dropdownStyleData: DropdownStyleData( - maxHeight: MediaQuery.of(context).size.height * 0.4, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10), - ), - ), - dropdownSearchData: DropdownSearchData( - searchController: _searchController, - searchInnerWidgetHeight: 50, - searchInnerWidget: Container( - height: 50, - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), - child: TextFormField( - style: const TextStyle(color: Colors.black), - controller: _searchController, - decoration: InputDecoration( - isDense: true, - contentPadding: const EdgeInsets.symmetric( - horizontal: 10, - vertical: 12, - ), - hintText: 'Search for community...', - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - ), - ), + hintText: 'Search for community...', + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), ), ), - searchMatchFn: (item, searchValue) { - final communityName = (item.child as Text).data?.toLowerCase() ?? ''; - return communityName.contains(searchValue.toLowerCase().trim()); - }, - ), - onMenuStateChange: (isOpen) { - if (!isOpen) { - _searchController.clear(); - } - }, - menuItemStyleData: const MenuItemStyleData( - height: 40, ), ), - )); - }, - ), + searchMatchFn: (item, searchValue) { + final communityName = + (item.child as Text).data?.toLowerCase() ?? ''; + return communityName + .contains(searchValue.toLowerCase().trim()); + }, + ), + onMenuStateChange: (isOpen) { + if (!isOpen) { + _searchController.clear(); + } + }, + menuItemStyleData: const MenuItemStyleData( + height: 40, + ), + ), + )) ], ), ); diff --git a/lib/pages/routines/create_new_routines/create_new_routines.dart b/lib/pages/routines/create_new_routines/create_new_routines.dart index baf10748..4900af9b 100644 --- a/lib/pages/routines/create_new_routines/create_new_routines.dart +++ b/lib/pages/routines/create_new_routines/create_new_routines.dart @@ -5,11 +5,10 @@ import 'package:syncrow_web/pages/routines/bloc/create_routine_bloc/create_routi import 'package:syncrow_web/pages/routines/bloc/create_routine_bloc/create_routine_bloc.dart'; import 'package:syncrow_web/pages/routines/create_new_routines/commu_dropdown.dart'; import 'package:syncrow_web/pages/routines/create_new_routines/space_dropdown.dart'; - import 'package:syncrow_web/utils/color_manager.dart'; class CreateNewRoutinesDialog extends StatefulWidget { - const CreateNewRoutinesDialog({Key? key}) : super(key: key); + const CreateNewRoutinesDialog({super.key}); @override State createState() => @@ -19,136 +18,162 @@ class CreateNewRoutinesDialog extends StatefulWidget { class _CreateNewRoutinesDialogState extends State { String? _selectedCommunity; String? _selectedSpace; - void _fetchSpaces(String communityId) { - context - .read() - .add(SpaceOnlyWithDevicesEvent(communityId)); - } @override Widget build(BuildContext context) { - return BlocBuilder( - builder: (context, state) { - final _bloc = BlocProvider.of(context); - final spaces = _bloc.spacesOnlyWithDevices; - final isLoading = state is SpaceWithDeviceLoadingState; + return BlocProvider( + create: (BuildContext context) => + CreateRoutineBloc()..add(const FetchCommunityEvent()), + child: BlocBuilder( + builder: (context, state) { + final _bloc = BlocProvider.of(context); + final spaces = _bloc.spacesOnlyWithDevices; + final isLoadingCommunities = state is CommunitiesLoadingState; + final isLoadingSpaces = state is SpaceWithDeviceLoadingState; + String spaceHint = 'Select a community first'; + if (_selectedCommunity != null) { + if (isLoadingSpaces) { + spaceHint = 'Loading spaces...'; + } else if (spaces.isEmpty) { + spaceHint = 'No spaces available'; + } else { + spaceHint = 'Select Space'; + } + } - String spaceHint = 'Select a community first'; - - if (_selectedCommunity != null) { - if (isLoading) { - spaceHint = 'Loading spaces...'; - } else if (spaces.isEmpty) { - spaceHint = 'No spaces available'; - } else { - spaceHint = 'Select Space'; - } - } - - return AlertDialog( - backgroundColor: Colors.white, - insetPadding: EdgeInsets.zero, - contentPadding: EdgeInsets.zero, - shape: - RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), - title: Text( - 'Create New Routines', - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.bodyMedium!.copyWith( - color: ColorsManager.primaryColor, - ), - ), - content: Column( - mainAxisSize: MainAxisSize.min, - children: [ - const Divider(), - Padding( - padding: const EdgeInsets.only(left: 15, right: 15), - child: CommunityDropdown( - selectedValue: _selectedCommunity, - onChanged: (String? newValue) { - setState(() { - _selectedCommunity = newValue; - _selectedSpace = null; - }); - if (newValue != null) { - _fetchSpaces(newValue); - } - }, - ), + return AlertDialog( + backgroundColor: Colors.white, + insetPadding: EdgeInsets.zero, + contentPadding: EdgeInsets.zero, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12)), + title: Text( + 'Create New Routines', + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.bodyMedium!.copyWith( + color: ColorsManager.primaryColor, + ), ), - const SizedBox(height: 5), - Padding( - padding: const EdgeInsets.only(left: 15, right: 15), - child: SpaceDropdown( - hintMessage: spaceHint, - spaces: spaces, - selectedValue: _selectedSpace, - onChanged: (String? newValue) { - setState(() { - _selectedSpace = newValue; - }); - }, - ), - ), - const Divider(), - Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, + content: Stack( children: [ - Padding( - padding: const EdgeInsets.only( - left: 20, - right: 20, - ), - child: TextButton( - onPressed: () { - Navigator.of(context).pop(); - }, - child: Text( - 'Cancel', - style: Theme.of(context).textTheme.bodyMedium!.copyWith( - fontWeight: FontWeight.w400, - fontSize: 14, - color: ColorsManager.blackColor, - ), + Column( + mainAxisSize: MainAxisSize.min, + children: [ + const Divider(), + Padding( + padding: const EdgeInsets.only(left: 15, right: 15), + child: CommunityDropdown( + communities: _bloc.communities, + selectedValue: _selectedCommunity, + onChanged: (String? newValue) { + setState(() { + _selectedCommunity = newValue; + _selectedSpace = null; + }); + if (newValue != null) { + _bloc.add(SpaceOnlyWithDevicesEvent(newValue)); + } + }, + ), ), - ), - ), - Padding( - padding: const EdgeInsets.only( - left: 20, - right: 20, - ), - child: TextButton( - onPressed: - _selectedCommunity != null && _selectedSpace != null - ? () { - Navigator.of(context).pop({ - 'community': _selectedCommunity, - 'space': _selectedSpace, - }); - } - : null, - child: Text( - 'Next', - style: Theme.of(context).textTheme.bodyMedium!.copyWith( - fontWeight: FontWeight.w400, - fontSize: 14, - color: _selectedCommunity != null && + const SizedBox(height: 5), + Padding( + padding: const EdgeInsets.only(left: 15, right: 15), + child: SpaceDropdown( + hintMessage: spaceHint, + spaces: spaces, + selectedValue: _selectedSpace, + onChanged: (String? newValue) { + setState(() { + _selectedSpace = newValue; + }); + }, + ), + ), + const Divider(), + Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + Padding( + padding: const EdgeInsets.only( + left: 20, + right: 20, + ), + child: TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: Text( + 'Cancel', + style: Theme.of(context) + .textTheme + .bodyMedium! + .copyWith( + fontWeight: FontWeight.w400, + fontSize: 14, + color: ColorsManager.blackColor, + ), + ), + ), + ), + Padding( + padding: const EdgeInsets.only( + left: 20, + right: 20, + ), + child: TextButton( + onPressed: _selectedCommunity != null && _selectedSpace != null - ? ColorsManager.blueColor - : Colors.blue.shade100, + ? () { + Navigator.of(context).pop({ + 'community': _selectedCommunity, + 'space': _selectedSpace, + }); + } + : null, + child: Text( + 'Next', + style: Theme.of(context) + .textTheme + .bodyMedium! + .copyWith( + fontWeight: FontWeight.w400, + fontSize: 14, + color: _selectedCommunity != null && + _selectedSpace != null + ? ColorsManager.blueColor + : Colors.blue.shade100, + ), + ), ), + ), + ], + ), + const SizedBox(height: 10), + ], + ), + if (isLoadingCommunities) + const SizedBox( + height: 200, + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Center( + child: Center( + child: CircularProgressIndicator( + color: ColorsManager.primaryColor, + ), + ), + ), + ], ), ), - ), ], ), - SizedBox(height: 10), - ], - ), - ); - }, - ); + ); + }, + )); } } diff --git a/lib/pages/routines/widgets/if_container.dart b/lib/pages/routines/widgets/if_container.dart index d6078143..eebf3fb7 100644 --- a/lib/pages/routines/widgets/if_container.dart +++ b/lib/pages/routines/widgets/if_container.dart @@ -105,9 +105,7 @@ class IfContainer extends StatelessWidget { ); }, onAcceptWithDetails: (data) async { - print('data.data=${data.data}'); final uniqueCustomId = const Uuid().v4(); - final mutableData = Map.from(data.data); mutableData['uniqueCustomId'] = uniqueCustomId;