UI enhancement
This commit is contained in:
parent
02758a03bf
commit
a11fc80050
@ -164,47 +164,45 @@ class _AssignTaskBottomSheetState extends State<AssignTaskBottomSheet> {
|
||||
GestureDetector(
|
||||
onTap: _openEmployeeSelectionSheet,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: Colors.grey.shade300),
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(Icons.group, color: Colors.black54),
|
||||
const SizedBox(width: 10),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: Colors.grey.shade300),
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(Icons.group, color: Colors.black54),
|
||||
const SizedBox(width: 10),
|
||||
|
||||
// Expanded name area
|
||||
Expanded(
|
||||
child: Obx(() {
|
||||
final count = controller.selectedEmployees.length;
|
||||
if (count == 0) {
|
||||
return MyText(
|
||||
"Select team members",
|
||||
color: Colors.grey.shade700,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
);
|
||||
}
|
||||
// Expanded name area
|
||||
Expanded(
|
||||
child: Obx(() {
|
||||
final count = controller.selectedEmployees.length;
|
||||
if (count == 0) {
|
||||
return MyText(
|
||||
"Select team members",
|
||||
color: Colors.grey.shade700,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
);
|
||||
}
|
||||
|
||||
final names = controller.selectedEmployees
|
||||
.map((e) => e.name)
|
||||
.join(", ");
|
||||
final names = controller.selectedEmployees
|
||||
.map((e) => e.name)
|
||||
.join(", ");
|
||||
|
||||
return Text(
|
||||
names,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(fontSize: 14),
|
||||
);
|
||||
}),
|
||||
),
|
||||
return Text(
|
||||
names,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
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),
|
||||
@ -272,20 +270,14 @@ class _AssignTaskBottomSheetState extends State<AssignTaskBottomSheet> {
|
||||
spacing: 4,
|
||||
runSpacing: 4,
|
||||
children: controller.selectedEmployees.map((e) {
|
||||
return Obx(() {
|
||||
final isSelected = controller.uploadingStates[e.id]?.value ?? false;
|
||||
if (!isSelected) return Container();
|
||||
|
||||
return Chip(
|
||||
label: Text(e.name, style: const TextStyle(color: Colors.white)),
|
||||
backgroundColor: const Color.fromARGB(255, 95, 132, 255),
|
||||
deleteIcon: const Icon(Icons.close, color: Colors.white),
|
||||
onDeleted: () {
|
||||
controller.uploadingStates[e.id]?.value = false;
|
||||
controller.updateSelectedEmployees();
|
||||
},
|
||||
);
|
||||
});
|
||||
return Chip(
|
||||
label: Text(e.name, style: const TextStyle(color: Colors.white)),
|
||||
backgroundColor: const Color.fromARGB(255, 95, 132, 255),
|
||||
deleteIcon: const Icon(Icons.close, color: Colors.white),
|
||||
onDeleted: () {
|
||||
controller.selectedEmployees.remove(e);
|
||||
},
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
});
|
||||
@ -380,7 +372,6 @@ class _AssignTaskBottomSheetState extends State<AssignTaskBottomSheet> {
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
|
||||
),
|
||||
|
||||
child: MultipleSelectRoleBottomSheet(
|
||||
projectId: selectedProjectId!,
|
||||
organizationId: selectedOrganization?.id,
|
||||
@ -396,16 +387,13 @@ class _AssignTaskBottomSheetState extends State<AssignTaskBottomSheet> {
|
||||
);
|
||||
|
||||
if (result != null) {
|
||||
controller.selectedEmployees.assignAll(result);
|
||||
controller.updateSelectedEmployees();
|
||||
controller.selectedEmployees
|
||||
.assignAll(result); // RxList updates UI automatically
|
||||
}
|
||||
}
|
||||
|
||||
void _onAssignTaskPressed() {
|
||||
final selectedTeam = controller.uploadingStates.entries
|
||||
.where((e) => e.value.value)
|
||||
.map((e) => e.key)
|
||||
.toList();
|
||||
final selectedTeam = controller.selectedEmployees;
|
||||
|
||||
if (selectedTeam.isEmpty) {
|
||||
showAppSnackbar(
|
||||
@ -449,7 +437,7 @@ class _AssignTaskBottomSheetState extends State<AssignTaskBottomSheet> {
|
||||
workItemId: widget.workItemId,
|
||||
plannedTask: target.toInt(),
|
||||
description: description,
|
||||
taskTeam: selectedTeam,
|
||||
taskTeam: selectedTeam.map((e) => e.id).toList(), // pass IDs
|
||||
assignmentDate: widget.assignmentDate,
|
||||
organizationId: selectedOrganization?.id,
|
||||
serviceId: selectedService?.id,
|
||||
|
||||
@ -68,13 +68,18 @@ class _EmployeeSelectionBottomSheetState
|
||||
.toList();
|
||||
|
||||
// ------------------------------------------------------
|
||||
// 🔥 Auto-move selected employees to top
|
||||
// Auto-move selected employees to top
|
||||
// ------------------------------------------------------
|
||||
results.sort((a, b) {
|
||||
final aSel = _selectedEmployees.contains(a) ? 0 : 1;
|
||||
final bSel = _selectedEmployees.contains(b) ? 0 : 1;
|
||||
if (widget.multipleSelection) {
|
||||
// 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());
|
||||
});
|
||||
|
||||
|
||||
@ -63,7 +63,6 @@ class _MultipleSelectRoleBottomSheetState
|
||||
employees.where((emp) => emp.jobRoleID == widget.roleId).toList();
|
||||
}
|
||||
|
||||
// Selected first
|
||||
employees.sort((a, b) {
|
||||
final aSel = _selected.any((e) => e.id == a.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) {
|
||||
final aSel = _selected.any((e) => e.id == a.id) ? 0 : 1;
|
||||
final bSel = _selected.any((e) => e.id == b.id) ? 0 : 1;
|
||||
@ -110,8 +108,8 @@ class _MultipleSelectRoleBottomSheetState
|
||||
_selected.add(emp);
|
||||
}
|
||||
} else {
|
||||
_selected.assignAll([emp]);
|
||||
Get.back(result: _selected);
|
||||
// Single selection → return immediately
|
||||
Get.back(result: [emp]);
|
||||
}
|
||||
|
||||
_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
|
||||
Widget build(BuildContext context) {
|
||||
return BaseBottomSheet(
|
||||
title: widget.title,
|
||||
onCancel: () => Get.back(),
|
||||
onSubmit: () => Get.back(result: _selected),
|
||||
onSubmit: () => Get.back(result: _selected.toList()), // Return plain list
|
||||
child: SizedBox(
|
||||
height: MediaQuery.of(context).size.height * 0.55,
|
||||
child: Column(
|
||||
children: [
|
||||
_searchBar(),
|
||||
|
||||
/// ⭐ Chips shown right below search bar
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: _selectedChips(),
|
||||
),
|
||||
|
||||
const SizedBox(height: 6),
|
||||
|
||||
Expanded(
|
||||
child: Obx(() {
|
||||
if (_isLoading.value) {
|
||||
@ -228,13 +194,12 @@ class _MultipleSelectRoleBottomSheetState
|
||||
fillColor:
|
||||
MaterialStateProperty.resolveWith<Color>((states) {
|
||||
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
|
||||
side: const BorderSide(
|
||||
color: Colors.grey), // Outline for unselected
|
||||
checkColor: Colors.white,
|
||||
side: const BorderSide(color: Colors.grey),
|
||||
),
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
horizontal: 4,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user