UI enhancement

This commit is contained in:
Manish 2025-11-21 17:36:56 +05:30
parent 17d1a66e1b
commit 83e1686778
3 changed files with 53 additions and 86 deletions

View File

@ -166,47 +166,45 @@ class _AssignTaskBottomSheetState extends State<AssignTaskBottomSheet> {
GestureDetector( GestureDetector(
onTap: _openEmployeeSelectionSheet, onTap: _openEmployeeSelectionSheet,
child: Container( child: Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12), padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12),
decoration: BoxDecoration( decoration: BoxDecoration(
border: Border.all(color: Colors.grey.shade300), border: Border.all(color: Colors.grey.shade300),
borderRadius: BorderRadius.circular(6), borderRadius: BorderRadius.circular(6),
), ),
child: Row( child: Row(
children: [ children: [
const Icon(Icons.group, color: Colors.black54), const Icon(Icons.group, color: Colors.black54),
const SizedBox(width: 10), const SizedBox(width: 10),
// Expanded name area // Expanded name area
Expanded( Expanded(
child: Obx(() { child: Obx(() {
final count = controller.selectedEmployees.length; final count = controller.selectedEmployees.length;
if (count == 0) { if (count == 0) {
return MyText( return MyText(
"Select team members", "Select team members",
color: Colors.grey.shade700, color: Colors.grey.shade700,
maxLines: 1, maxLines: 1,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
); );
} }
final names = controller.selectedEmployees final names = controller.selectedEmployees
.map((e) => e.name) .map((e) => e.name)
.join(", "); .join(", ");
return Text( return Text(
names, names,
maxLines: 2, maxLines: 2,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: const TextStyle(fontSize: 14), style: const TextStyle(fontSize: 14),
); );
}), }),
), ),
const Icon(Icons.arrow_drop_down, color: Colors.grey), const Icon(Icons.arrow_drop_down, color: Colors.grey),
], ],
) )),
),
), ),
MySpacing.height(8), MySpacing.height(8),
@ -381,7 +379,6 @@ class _AssignTaskBottomSheetState extends State<AssignTaskBottomSheet> {
color: Colors.white, color: Colors.white,
borderRadius: BorderRadius.vertical(top: Radius.circular(20)), borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
), ),
child: MultipleSelectRoleBottomSheet( child: MultipleSelectRoleBottomSheet(
projectId: selectedProjectId!, projectId: selectedProjectId!,
organizationId: selectedOrganization?.id, organizationId: selectedOrganization?.id,
@ -397,8 +394,8 @@ class _AssignTaskBottomSheetState extends State<AssignTaskBottomSheet> {
); );
if (result != null) { if (result != null) {
controller.selectedEmployees.assignAll(result); controller.selectedEmployees
controller.updateSelectedEmployees(); .assignAll(result); // RxList updates UI automatically
} }
} }

View File

@ -68,13 +68,18 @@ class _EmployeeSelectionBottomSheetState
.toList(); .toList();
// ------------------------------------------------------ // ------------------------------------------------------
// 🔥 Auto-move selected employees to top // Auto-move selected employees to top
// ------------------------------------------------------ // ------------------------------------------------------
results.sort((a, b) { results.sort((a, b) {
final aSel = _selectedEmployees.contains(a) ? 0 : 1; if (widget.multipleSelection) {
final bSel = _selectedEmployees.contains(b) ? 0 : 1; // Only move selected employees to top in multi-select
final aSel = _selectedEmployees.contains(a) ? 0 : 1;
final bSel = _selectedEmployees.contains(b) ? 0 : 1;
if (aSel != bSel) return aSel.compareTo(bSel); if (aSel != bSel) return aSel.compareTo(bSel);
}
// Otherwise, keep original order (or alphabetically if needed)
return a.name.toLowerCase().compareTo(b.name.toLowerCase()); return a.name.toLowerCase().compareTo(b.name.toLowerCase());
}); });

View File

@ -63,7 +63,6 @@ class _MultipleSelectRoleBottomSheetState
employees.where((emp) => emp.jobRoleID == widget.roleId).toList(); employees.where((emp) => emp.jobRoleID == widget.roleId).toList();
} }
// Selected first
employees.sort((a, b) { employees.sort((a, b) {
final aSel = _selected.any((e) => e.id == a.id) ? 0 : 1; final aSel = _selected.any((e) => e.id == a.id) ? 0 : 1;
final bSel = _selected.any((e) => e.id == b.id) ? 0 : 1; final bSel = _selected.any((e) => e.id == b.id) ? 0 : 1;
@ -92,7 +91,6 @@ class _MultipleSelectRoleBottomSheetState
); );
} }
// Selected on top
_filtered.sort((a, b) { _filtered.sort((a, b) {
final aSel = _selected.any((e) => e.id == a.id) ? 0 : 1; final aSel = _selected.any((e) => e.id == a.id) ? 0 : 1;
final bSel = _selected.any((e) => e.id == b.id) ? 0 : 1; final bSel = _selected.any((e) => e.id == b.id) ? 0 : 1;
@ -110,8 +108,8 @@ class _MultipleSelectRoleBottomSheetState
_selected.add(emp); _selected.add(emp);
} }
} else { } else {
_selected.assignAll([emp]); // Single selection return immediately
Get.back(result: _selected); Get.back(result: [emp]);
} }
_onSearch(_searchController.text.trim()); _onSearch(_searchController.text.trim());
@ -150,49 +148,17 @@ class _MultipleSelectRoleBottomSheetState
), ),
); );
/// NEW Chips showing selected employees
Widget _selectedChips() {
return Obx(() {
if (_selected.isEmpty) return const SizedBox();
return Wrap(
spacing: 8,
runSpacing: 8,
children: _selected.map((emp) {
return Chip(
label: Text(emp.name),
deleteIcon: const Icon(Icons.close),
onDeleted: () {
_selected.remove(emp);
_onSearch(_searchController.text.trim());
},
backgroundColor: Colors.blue.shade50,
);
}).toList(),
);
});
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BaseBottomSheet( return BaseBottomSheet(
title: widget.title, title: widget.title,
onCancel: () => Get.back(), onCancel: () => Get.back(),
onSubmit: () => Get.back(result: _selected), onSubmit: () => Get.back(result: _selected.toList()), // Return plain list
child: SizedBox( child: SizedBox(
height: MediaQuery.of(context).size.height * 0.55, height: MediaQuery.of(context).size.height * 0.55,
child: Column( child: Column(
children: [ children: [
_searchBar(), _searchBar(),
/// Chips shown right below search bar
Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: _selectedChips(),
),
const SizedBox(height: 6),
Expanded( Expanded(
child: Obx(() { child: Obx(() {
if (_isLoading.value) { if (_isLoading.value) {
@ -228,13 +194,12 @@ class _MultipleSelectRoleBottomSheetState
fillColor: fillColor:
MaterialStateProperty.resolveWith<Color>((states) { MaterialStateProperty.resolveWith<Color>((states) {
if (states.contains(MaterialState.selected)) { if (states.contains(MaterialState.selected)) {
return Colors.blueAccent; // Selected color return Colors.blueAccent;
} }
return Colors.white; // Unselected square color return Colors.white;
}), }),
checkColor: Colors.white, // Check mark color checkColor: Colors.white,
side: const BorderSide( side: const BorderSide(color: Colors.grey),
color: Colors.grey), // Outline for unselected
), ),
contentPadding: const EdgeInsets.symmetric( contentPadding: const EdgeInsets.symmetric(
horizontal: 4, horizontal: 4,