111 lines
3.2 KiB
Dart
111 lines
3.2 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:get/get.dart';
|
|
import 'package:on_field_work/helpers/services/api_service.dart';
|
|
import 'package:on_field_work/helpers/widgets/my_snackbar.dart';
|
|
import 'package:on_field_work/controller/service_project/service_project_details_screen_controller.dart';
|
|
import 'package:on_field_work/model/employees/employee_model.dart';
|
|
import 'package:on_field_work/model/service_project/service_project_branches_model.dart';
|
|
|
|
class AddServiceProjectJobController extends GetxController {
|
|
// FORM CONTROLLERS
|
|
final titleCtrl = TextEditingController();
|
|
final descCtrl = TextEditingController();
|
|
final tagCtrl = TextEditingController();
|
|
final searchFocusNode = FocusNode();
|
|
|
|
// OBSERVABLES
|
|
final startDate = Rx<DateTime?>(DateTime.now());
|
|
final dueDate = Rx<DateTime?>(DateTime.now().add(const Duration(days: 1)));
|
|
|
|
final enteredTags = <String>[].obs;
|
|
final selectedAssignees = <EmployeeModel>[].obs;
|
|
|
|
// Branches
|
|
final branches = <Branch>[].obs;
|
|
final selectedBranch = Rxn<Branch>();
|
|
final isBranchLoading = false.obs;
|
|
|
|
// Loading
|
|
final isLoading = false.obs;
|
|
|
|
@override
|
|
void onClose() {
|
|
titleCtrl.dispose();
|
|
descCtrl.dispose();
|
|
tagCtrl.dispose();
|
|
searchFocusNode.dispose();
|
|
super.onClose();
|
|
}
|
|
|
|
// FETCH BRANCHES
|
|
Future<void> fetchBranches(String projectId) async {
|
|
isBranchLoading.value = true;
|
|
|
|
final response = await ApiService.getServiceProjectBranchesFull(
|
|
projectId: projectId,
|
|
);
|
|
|
|
if (response != null && response.success) {
|
|
branches.assignAll(response.data?.data ?? []);
|
|
}
|
|
|
|
isBranchLoading.value = false;
|
|
}
|
|
|
|
// CREATE JOB
|
|
Future<void> createJob(String projectId) async {
|
|
if (titleCtrl.text.trim().isEmpty || descCtrl.text.trim().isEmpty) {
|
|
showAppSnackbar(
|
|
title: "Validation",
|
|
message: "Title and Description are required",
|
|
type: SnackbarType.warning,
|
|
);
|
|
return;
|
|
}
|
|
|
|
isLoading.value = true;
|
|
|
|
final jobId = await ApiService.createServiceProjectJobApi(
|
|
title: titleCtrl.text.trim(),
|
|
description: descCtrl.text.trim(),
|
|
projectId: projectId,
|
|
branchId: selectedBranch.value?.id,
|
|
assignees: selectedAssignees // payload mapping
|
|
.map((e) => {"employeeId": e.id, "isActive": true})
|
|
.toList(),
|
|
startDate: startDate.value!,
|
|
dueDate: dueDate.value!,
|
|
tags: enteredTags
|
|
.map((tag) => {"id": null, "name": tag, "isActive": true})
|
|
.toList(),
|
|
);
|
|
|
|
isLoading.value = false;
|
|
|
|
if (jobId != null) {
|
|
if (Get.isRegistered<ServiceProjectDetailsController>()) {
|
|
final detailsCtrl = Get.find<ServiceProjectDetailsController>();
|
|
|
|
// 🔥 1. Refresh job LIST
|
|
detailsCtrl.refreshJobsAfterAdd();
|
|
|
|
// 🔥 2. Refresh job DETAILS (FULL DATA - including tags and assignees)
|
|
await detailsCtrl.fetchJobDetail(jobId);
|
|
}
|
|
|
|
Get.back();
|
|
showAppSnackbar(
|
|
title: "Success",
|
|
message: "Job created successfully",
|
|
type: SnackbarType.success,
|
|
);
|
|
} else {
|
|
showAppSnackbar(
|
|
title: "Error",
|
|
message: "Failed to create job",
|
|
type: SnackbarType.error,
|
|
);
|
|
}
|
|
}
|
|
}
|