Merge pull request #126 from SyncrowIOT/fix_routine_popup

Refactor routine creation UI for improved code organization
This commit is contained in:
mohammadnemer1
2025-03-27 15:06:38 +03:00
committed by GitHub
4 changed files with 229 additions and 112 deletions

View File

@ -1,16 +1,16 @@
import 'package:dropdown_button2/dropdown_button2.dart';
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/pages/space_tree/bloc/space_tree_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/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 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/style.dart';
class CommunityDropdown extends StatelessWidget { class CommunityDropdown extends StatelessWidget {
final String? selectedValue; final String? selectedValue;
final Function(String?) onChanged; final Function(String?) onChanged;
final TextEditingController _searchController = TextEditingController();
const CommunityDropdown({ CommunityDropdown({
Key? key, Key? key,
required this.selectedValue, required this.selectedValue,
required this.onChanged, required this.onChanged,
@ -34,59 +34,125 @@ class CommunityDropdown extends StatelessWidget {
const SizedBox(height: 8), const SizedBox(height: 8),
BlocBuilder<SpaceTreeBloc, SpaceTreeState>( BlocBuilder<SpaceTreeBloc, SpaceTreeState>(
builder: (context, state) { builder: (context, state) {
List<CommunityModel> communities = state.isSearching
? state.filteredCommunity
: state.communityList;
return SizedBox( return SizedBox(
child: DropdownButtonFormField<String>( child: Container(
dropdownColor: ColorsManager.whiteColors, decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
),
child: DropdownButton2<String>(
underline: SizedBox(),
value: selectedValue, value: selectedValue,
items: communities.map((community) { items: state.communityList.map((community) {
return DropdownMenuItem<String>( return DropdownMenuItem<String>(
value: community.uuid, value: community.uuid,
child: Text(' ${community.name}'), child: Text(
' ${community.name}',
overflow: TextOverflow.ellipsis,
maxLines: 1,
),
); );
}).toList(), }).toList(),
onChanged: onChanged, onChanged: onChanged,
icon: const SizedBox.shrink(), style: TextStyle(color: Colors.black),
borderRadius: const BorderRadius.all(Radius.circular(10)),
hint: Padding( hint: Padding(
padding: EdgeInsets.only(left: 10), padding: EdgeInsets.only(left: 10),
child: Text( child: Text(
"Please Select", " Please Select",
style: Theme.of(context).textTheme.bodySmall!.copyWith( style: Theme.of(context).textTheme.bodySmall!.copyWith(
color: ColorsManager.textGray, color: ColorsManager.textGray,
), ),
), ),
), ),
decoration: inputTextFormDeco().copyWith( customButton: Container(
contentPadding: EdgeInsets.zero, height: 45,
suffixIcon: Container( decoration: BoxDecoration(
padding: EdgeInsets.zero, border:
width: 70, Border.all(color: ColorsManager.textGray, width: 1.0),
height: 45, borderRadius: BorderRadius.circular(10),
decoration: BoxDecoration( ),
color: Colors.grey[100], child: Row(
borderRadius: const BorderRadius.only( mainAxisAlignment: MainAxisAlignment.spaceBetween,
bottomRight: Radius.circular(10), children: [
topRight: Radius.circular(10), 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,
),
), ),
border: Border.all( Expanded(
color: ColorsManager.textGray, child: Container(
width: 1.0, 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,
),
),
), ),
), ],
child: const Center( ),
child: Icon( ),
Icons.keyboard_arrow_down, dropdownStyleData: DropdownStyleData(
color: ColorsManager.textGray, 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),
),
), ),
), ),
), ),
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,
), ),
), ),
); ));
}, },
), ),
], ],

View File

@ -62,28 +62,34 @@ class _CreateNewRoutinesDialogState extends State<CreateNewRoutinesDialog> {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
const Divider(), const Divider(),
CommunityDropdown( Padding(
selectedValue: _selectedCommunity, padding: const EdgeInsets.only(left: 15, right: 15),
onChanged: (String? newValue) { child: CommunityDropdown(
setState(() { selectedValue: _selectedCommunity,
_selectedCommunity = newValue; onChanged: (String? newValue) {
_selectedSpace = null; setState(() {
}); _selectedCommunity = newValue;
if (newValue != null) { _selectedSpace = null;
_fetchSpaces(newValue); });
} if (newValue != null) {
}, _fetchSpaces(newValue);
}
},
),
), ),
const SizedBox(height: 16), const SizedBox(height: 5),
SpaceDropdown( Padding(
hintMessage: spaceHint, padding: const EdgeInsets.only(left: 15, right: 15),
spaces: spaces, child: SpaceDropdown(
selectedValue: _selectedSpace, hintMessage: spaceHint,
onChanged: (String? newValue) { spaces: spaces,
setState(() { selectedValue: _selectedSpace,
_selectedSpace = newValue; onChanged: (String? newValue) {
}); setState(() {
}, _selectedSpace = newValue;
});
},
),
), ),
const Divider(), const Divider(),
Row( Row(
@ -96,7 +102,6 @@ class _CreateNewRoutinesDialogState extends State<CreateNewRoutinesDialog> {
), ),
child: TextButton( child: TextButton(
onPressed: () { onPressed: () {
Navigator.of(context).pop(); Navigator.of(context).pop();
}, },
child: Text( child: Text(
@ -139,6 +144,7 @@ class _CreateNewRoutinesDialogState extends State<CreateNewRoutinesDialog> {
), ),
], ],
), ),
SizedBox(height: 10),
], ],
), ),
); );

View File

@ -1,7 +1,8 @@
import 'package:dropdown_button2/dropdown_button2.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart'; import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart';
import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/style.dart';
class SpaceDropdown extends StatelessWidget { class SpaceDropdown extends StatelessWidget {
final List<SpaceModel> spaces; final List<SpaceModel> spaces;
@ -33,62 +34,108 @@ class SpaceDropdown extends StatelessWidget {
), ),
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
DropdownButtonFormField<String>( SizedBox(
value: selectedValue, child: Container(
items: spaces.map((space) { decoration: BoxDecoration(
return DropdownMenuItem<String>( borderRadius: BorderRadius.circular(10),
value: space.uuid,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
' ${space.name}',
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
fontSize: 12,
color: ColorsManager.blackColor,
),
),
Text(
' ${space.lastThreeParents}',
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
fontSize: 12,
),
),
],
));
}).toList(),
onChanged: onChanged,
icon: const SizedBox.shrink(),
borderRadius: const BorderRadius.all(Radius.circular(10)),
hint: Padding(
padding: const EdgeInsets.only(left: 10),
child: Text(
hintMessage,
style: Theme.of(context).textTheme.bodySmall!.copyWith(
color: ColorsManager.textGray,
),
), ),
), child: DropdownButton2<String>(
decoration: inputTextFormDeco().copyWith( underline: const SizedBox(),
contentPadding: EdgeInsets.zero, value: selectedValue,
suffixIcon: Container( items: spaces.map((space) {
width: 70, return DropdownMenuItem<String>(
height: 45, value: space.uuid,
decoration: BoxDecoration( child: Column(
color: Colors.grey[200], crossAxisAlignment: CrossAxisAlignment.start,
borderRadius: const BorderRadius.only( mainAxisAlignment: MainAxisAlignment.start,
bottomRight: Radius.circular(10), children: [
topRight: Radius.circular(10), Text(
), ' ${space.name}',
border: Border.all( style:
color: ColorsManager.textGray, Theme.of(context).textTheme.bodyMedium!.copyWith(
width: 1.0, fontSize: 12,
color: ColorsManager.blackColor,
),
),
Text(
' ${space.lastThreeParents}',
style:
Theme.of(context).textTheme.bodyMedium!.copyWith(
fontSize: 12,
),
),
],
),
);
}).toList(),
onChanged: onChanged,
style: TextStyle(color: Colors.black),
hint: Padding(
padding: const EdgeInsets.only(left: 10),
child: Text(
hintMessage,
style: Theme.of(context).textTheme.bodySmall!.copyWith(
color: ColorsManager.textGray,
),
), ),
), ),
child: const Icon( customButton: Container(
Icons.keyboard_arrow_down, height: 45,
color: ColorsManager.textGray, 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: Padding(
padding: const EdgeInsets.only(left: 10),
child: Text(
selectedValue != null
? spaces
.firstWhere((e) => e.uuid == selectedValue)
.name
: hintMessage,
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[200],
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),
),
),
menuItemStyleData: const MenuItemStyleData(
height: 60,
), ),
), ),
), ),

View File

@ -33,8 +33,6 @@ class _RoutinesViewState extends State<RoutinesView> {
communityID: communityId, spaceID: spaceId)); communityID: communityId, spaceID: spaceId));
await Future.delayed(const Duration(seconds: 1)); await Future.delayed(const Duration(seconds: 1));
routineBloc.add(const CreateNewRoutineViewEvent(createRoutineView: true)); routineBloc.add(const CreateNewRoutineViewEvent(createRoutineView: true));
await Future.delayed(const Duration(milliseconds:500));
_bloc.add(const ResetSelectedEvent());
} }
@override @override