UI enhancement
This commit is contained in:
parent
17d1a66e1b
commit
83e1686778
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user