done tags UX updates
This commit is contained in:
parent
a85bea54f8
commit
4daa412a87
@ -75,7 +75,7 @@ class AddServiceProjectJobController extends GetxController {
|
||||
assignees: assigneeIds.map((id) => {"id": id}).toList(),
|
||||
startDate: startDate.value!,
|
||||
dueDate: dueDate.value!,
|
||||
tags: enteredTags.map((tag) => {"name": tag}).toList(),
|
||||
tags: enteredTags.map((tag) => {"name": tag.trim()}).toList(),
|
||||
);
|
||||
|
||||
isLoading.value = false;
|
||||
|
||||
@ -204,11 +204,37 @@ class _AddServiceProjectJobBottomSheetState
|
||||
height: 48,
|
||||
child: TextFormField(
|
||||
controller: controller.tagCtrl,
|
||||
textInputAction: TextInputAction.done,
|
||||
onEditingComplete: () {
|
||||
final raw = controller.tagCtrl.text.trim();
|
||||
if (raw.isEmpty) return;
|
||||
|
||||
final parts = raw
|
||||
.split(',')
|
||||
.map((s) => s.trim())
|
||||
.where((s) => s.isNotEmpty);
|
||||
|
||||
for (final p in parts) {
|
||||
if (!controller.enteredTags.contains(p)) {
|
||||
controller.enteredTags.add(p);
|
||||
}
|
||||
}
|
||||
controller.tagCtrl.clear();
|
||||
},
|
||||
onFieldSubmitted: (v) {
|
||||
final value = v.trim();
|
||||
if (value.isNotEmpty &&
|
||||
!controller.enteredTags.contains(value)) {
|
||||
controller.enteredTags.add(value);
|
||||
// also handle normal submit
|
||||
final raw = v.trim();
|
||||
if (raw.isEmpty) return;
|
||||
|
||||
final parts = raw
|
||||
.split(',')
|
||||
.map((s) => s.trim())
|
||||
.where((s) => s.isNotEmpty);
|
||||
|
||||
for (final p in parts) {
|
||||
if (!controller.enteredTags.contains(p)) {
|
||||
controller.enteredTags.add(p);
|
||||
}
|
||||
}
|
||||
controller.tagCtrl.clear();
|
||||
},
|
||||
|
||||
@ -201,7 +201,7 @@ class _JobsTabState extends State<JobsTab> {
|
||||
children: job.tags!.map((tag) {
|
||||
return Chip(
|
||||
label: Text(
|
||||
tag.name,
|
||||
tag.name.replaceAll('_', ' '),
|
||||
style:
|
||||
const TextStyle(fontSize: 12),
|
||||
),
|
||||
|
||||
@ -39,6 +39,10 @@ class _JobDetailsScreenState extends State<JobDetailsScreen> with UIMixin {
|
||||
final TextEditingController _dueDateController = TextEditingController();
|
||||
final TextEditingController _tagTextController = TextEditingController();
|
||||
|
||||
final RxList<String> tags = <String>[].obs; // For showing/editing tag chips
|
||||
final TextEditingController tagController =
|
||||
TextEditingController(); // For tag input
|
||||
|
||||
final RxList<Assignee> _selectedAssignees = <Assignee>[].obs;
|
||||
final RxList<Tag> _selectedTags = <Tag>[].obs;
|
||||
final RxBool isEditing = false.obs;
|
||||
@ -47,21 +51,38 @@ class _JobDetailsScreenState extends State<JobDetailsScreen> with UIMixin {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
controller = Get.put(ServiceProjectDetailsController());
|
||||
controller.fetchJobDetail(widget.jobId).then((_) {
|
||||
controller = Get.find<ServiceProjectDetailsController>();
|
||||
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||
await controller.fetchJobDetail(widget.jobId);
|
||||
|
||||
final job = controller.jobDetail.value?.data;
|
||||
if (job != null) {
|
||||
_titleController.text = job.title ?? '';
|
||||
_descriptionController.text = job.description ?? '';
|
||||
|
||||
_startDateController.text = DateTimeUtils.convertUtcToLocal(
|
||||
job.startDate ?? DateTime.now().toIso8601String(),
|
||||
format: "yyyy-MM-dd");
|
||||
|
||||
_dueDateController.text = DateTimeUtils.convertUtcToLocal(
|
||||
job.dueDate ?? '',
|
||||
format: "yyyy-MM-dd");
|
||||
|
||||
_selectedAssignees.value = job.assignees ?? [];
|
||||
_selectedTags.value = job.tags ?? [];
|
||||
|
||||
// ---------- TAG FIX ----------
|
||||
final tagList = job.tags ?? [];
|
||||
|
||||
final cleanedTags = tagList
|
||||
.map((t) => (t.name ?? "").replaceAll("_", " ").trim())
|
||||
.toList();
|
||||
|
||||
tags.assignAll(cleanedTags);
|
||||
tagController.clear();
|
||||
}
|
||||
|
||||
setState(() {});
|
||||
});
|
||||
}
|
||||
|
||||
@ -167,9 +188,19 @@ class _JobDetailsScreenState extends State<JobDetailsScreen> with UIMixin {
|
||||
showAppSnackbar(
|
||||
title: "Success",
|
||||
message: "Job updated successfully",
|
||||
type: SnackbarType.success);
|
||||
type: SnackbarType.success,
|
||||
);
|
||||
|
||||
/// Refresh detail screen
|
||||
await controller.fetchJobDetail(widget.jobId);
|
||||
|
||||
/// 🔥 Auto refresh job list UI (main Service Project Details screen)
|
||||
if (Get.isRegistered<ServiceProjectDetailsController>()) {
|
||||
await Get.find<ServiceProjectDetailsController>().refreshJobsAfterAdd();
|
||||
}
|
||||
|
||||
isEditing.value = false;
|
||||
Navigator.pop(context); // optional if you want auto-close
|
||||
} else {
|
||||
showAppSnackbar(
|
||||
title: "Error",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user