feat(bucket): add search functionality to Manage Buckets screen

This commit is contained in:
Vaibhav Surve 2025-07-15 10:52:36 +05:30
parent f9ab336eb0
commit 9c28dc05dd

View File

@ -23,7 +23,17 @@ class _ManageBucketsScreenState extends State<ManageBucketsScreen> {
final ManageBucketController manageBucketController =
Get.put(ManageBucketController());
final ProjectController projectController = Get.find();
final Map<String, bool> _expandedMap = {};
final TextEditingController searchController = TextEditingController();
String searchText = '';
void _clearSearch() {
searchController.clear();
setState(() {
searchText = '';
});
}
@override
Widget build(BuildContext context) {
@ -55,8 +65,7 @@ class _ManageBucketsScreenState extends State<ManageBucketsScreen> {
MyText.titleLarge('Manage Buckets',
fontWeight: 700, color: Colors.black),
MySpacing.height(2),
GetBuilder<ProjectController>(
builder: (_) {
GetBuilder<ProjectController>(builder: (_) {
final projectName =
projectController.selectedProject?.name ??
'Select Project';
@ -75,18 +84,63 @@ class _ManageBucketsScreenState extends State<ManageBucketsScreen> {
),
],
);
}),
],
),
),
],
),
),
),
),
body: Column(
children: [
Padding(
padding: MySpacing.xy(16, 12),
child: SizedBox(
height: 38,
child: TextField(
controller: searchController,
onChanged: (value) {
setState(() {
searchText = value.toLowerCase();
});
},
decoration: InputDecoration(
contentPadding:
const EdgeInsets.symmetric(horizontal: 12, vertical: 0),
prefixIcon: const Icon(Icons.search,
size: 18, color: Colors.grey),
suffixIcon: searchText.isNotEmpty
? IconButton(
icon: const Icon(Icons.close, color: Colors.grey),
onPressed: _clearSearch,
)
: null,
hintText: 'Search buckets...',
filled: true,
fillColor: Colors.white,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(color: Colors.grey.shade300),
),
],
),
),
],
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(color: Colors.grey.shade300),
),
),
),
),
body: Obx(() {
final buckets = directoryController.contactBuckets;
),
Expanded(
child: Obx(() {
final buckets = directoryController.contactBuckets.where((bucket) {
return bucket.name.toLowerCase().contains(searchText) ||
bucket.description.toLowerCase().contains(searchText) ||
bucket.numberOfContacts
.toString()
.contains(searchText);
}).toList();
if (directoryController.isLoading.value ||
manageBucketController.isLoading.value) {
@ -108,19 +162,18 @@ class _ManageBucketsScreenState extends State<ManageBucketsScreen> {
}
return ListView.separated(
padding: MySpacing.fromLTRB(16, 20, 16, 24),
padding: MySpacing.fromLTRB(16, 0, 16, 24),
itemCount: buckets.length,
separatorBuilder: (_, __) => MySpacing.height(16),
itemBuilder: (context, index) {
final bucket = buckets[index];
final isOwner =
currentUserId != null && bucket.createdBy.id == currentUserId;
final isOwner = currentUserId != null &&
bucket.createdBy.id == currentUserId;
final canEdit = isOwner ||
widget.permissionController
.hasPermission(Permissions.directoryAdmin) ||
widget.permissionController
.hasPermission(Permissions.directoryManager);
final isExpanded = _expandedMap[bucket.id] ?? false;
return Row(
@ -128,8 +181,8 @@ class _ManageBucketsScreenState extends State<ManageBucketsScreen> {
children: [
const Padding(
padding: EdgeInsets.only(top: 4),
child:
Icon(Icons.label_outline, size: 26, color: Colors.indigo),
child: Icon(Icons.label_outline,
size: 26, color: Colors.indigo),
),
MySpacing.width(12),
Expanded(
@ -153,10 +206,11 @@ class _ManageBucketsScreenState extends State<ManageBucketsScreen> {
padding: EdgeInsets.zero,
constraints: const BoxConstraints(),
onPressed: () {
final matchedEmployees = manageBucketController
.allEmployees
final matchedEmployees =
manageBucketController.allEmployees
.where((emp) =>
bucket.employeeIds.contains(emp.id))
bucket.employeeIds
.contains(emp.id))
.toList();
TeamMembersBottomSheet.show(
context, matchedEmployees);
@ -178,10 +232,11 @@ class _ManageBucketsScreenState extends State<ManageBucketsScreen> {
MySpacing.width(12),
GestureDetector(
onTap: () {
final matchedEmployees = manageBucketController
.allEmployees
final matchedEmployees =
manageBucketController.allEmployees
.where((emp) =>
bucket.employeeIds.contains(emp.id))
bucket.employeeIds
.contains(emp.id))
.toList();
TeamMembersBottomSheet.show(
context, matchedEmployees);
@ -222,7 +277,8 @@ class _ManageBucketsScreenState extends State<ManageBucketsScreen> {
final hasOverflow = tp.didExceedMaxLines;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
MyText.bodySmall(
bucket.description,
@ -236,11 +292,13 @@ class _ManageBucketsScreenState extends State<ManageBucketsScreen> {
GestureDetector(
onTap: () {
setState(() {
_expandedMap[bucket.id] = !isExpanded;
_expandedMap[bucket.id] =
!isExpanded;
});
},
child: Padding(
padding: const EdgeInsets.only(top: 4),
padding: const EdgeInsets.only(
top: 4),
child: MyText.labelSmall(
isExpanded
? "Show less"
@ -263,6 +321,9 @@ class _ManageBucketsScreenState extends State<ManageBucketsScreen> {
},
);
}),
),
],
),
);
}
}