220 lines
6.7 KiB
Dart
220 lines
6.7 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:get/get.dart';
|
|
import 'package:image_picker/image_picker.dart';
|
|
import 'package:geolocator/geolocator.dart';
|
|
|
|
import 'package:marco/helpers/services/api_service.dart';
|
|
import 'package:marco/model/attendance_model.dart';
|
|
import 'package:marco/model/project_model.dart';
|
|
import 'package:marco/model/employee_model.dart';
|
|
import 'package:marco/model/attendance_log_model.dart';
|
|
import 'package:marco/model/regularization_log_model.dart';
|
|
import 'package:marco/model/attendance_log_view_model.dart';
|
|
|
|
class AttendanceController extends GetxController {
|
|
List<AttendanceModel> attendances = [];
|
|
List<ProjectModel> projects = [];
|
|
String? selectedProjectId;
|
|
List<EmployeeModel> employees = [];
|
|
|
|
DateTime? startDateAttendance;
|
|
DateTime? endDateAttendance;
|
|
|
|
List<AttendanceLogModel> attendanceLogs = [];
|
|
List<RegularizationLogModel> regularizationLogs = [];
|
|
List<AttendanceLogViewModel> attendenceLogsView = [];
|
|
|
|
RxBool isLoading = false.obs; // Added loading flag
|
|
|
|
@override
|
|
void onInit() {
|
|
super.onInit();
|
|
_initializeDefaults();
|
|
}
|
|
|
|
void _initializeDefaults() {
|
|
_setDefaultDateRange();
|
|
fetchProjects();
|
|
}
|
|
|
|
void _setDefaultDateRange() {
|
|
final today = DateTime.now();
|
|
startDateAttendance = today.subtract(const Duration(days: 7));
|
|
endDateAttendance = today;
|
|
}
|
|
|
|
Future<void> fetchProjects() async {
|
|
isLoading.value = true; // Set loading to true before API call
|
|
final response = await ApiService.getProjects();
|
|
isLoading.value = false; // Set loading to false after API call completes
|
|
|
|
if (response != null && response.isNotEmpty) {
|
|
projects = response.map((json) => ProjectModel.fromJson(json)).toList();
|
|
selectedProjectId = projects.first.id.toString();
|
|
await _fetchProjectData(selectedProjectId);
|
|
update(['attendance_dashboard_controller']);
|
|
} else {
|
|
print("No projects data found or failed to fetch data.");
|
|
}
|
|
}
|
|
|
|
Future<void> _fetchProjectData(String? projectId) async {
|
|
if (projectId == null) return;
|
|
|
|
isLoading.value = true; // Set loading to true before API call
|
|
await Future.wait([
|
|
fetchEmployeesByProject(projectId),
|
|
fetchAttendanceLogs(projectId, dateFrom: startDateAttendance, dateTo: endDateAttendance),
|
|
fetchRegularizationLogs(projectId),
|
|
]);
|
|
isLoading.value = false; // Set loading to false after data is fetched
|
|
}
|
|
|
|
Future<void> fetchEmployeesByProject(String? projectId) async {
|
|
if (projectId == null) return;
|
|
|
|
isLoading.value = true; // Set loading to true before API call
|
|
final response = await ApiService.getEmployeesByProject(int.parse(projectId));
|
|
isLoading.value = false; // Set loading to false after API call completes
|
|
|
|
if (response != null) {
|
|
employees = response.map((json) => EmployeeModel.fromJson(json)).toList();
|
|
update();
|
|
} else {
|
|
print("Failed to fetch employees for project $projectId.");
|
|
}
|
|
}
|
|
|
|
Future<bool> captureAndUploadAttendance(
|
|
int id,
|
|
int employeeId,
|
|
int projectId, {
|
|
String comment = "Marked via mobile app",
|
|
required int action,
|
|
bool imageCapture = true, // <- add this flag
|
|
}) async {
|
|
try {
|
|
XFile? image;
|
|
if (imageCapture) {
|
|
image = await ImagePicker().pickImage(
|
|
source: ImageSource.camera,
|
|
imageQuality: 80,
|
|
);
|
|
if (image == null) return false;
|
|
}
|
|
|
|
final position = await Geolocator.getCurrentPosition(
|
|
desiredAccuracy: LocationAccuracy.high,
|
|
);
|
|
|
|
final imageName = imageCapture
|
|
? ApiService.generateImageName(employeeId, employees.length + 1)
|
|
: ""; // Empty or null if not capturing image
|
|
|
|
return await ApiService.uploadAttendanceImage(
|
|
id,
|
|
employeeId,
|
|
image,
|
|
position.latitude,
|
|
position.longitude,
|
|
imageName: imageName,
|
|
projectId: projectId,
|
|
comment: comment,
|
|
action: action,
|
|
imageCapture: imageCapture, // <- pass flag down
|
|
);
|
|
} catch (e) {
|
|
print("Error capturing or uploading attendance: $e");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
Future<void> selectDateRangeForAttendance(
|
|
BuildContext context,
|
|
AttendanceController controller,
|
|
) async {
|
|
final picked = await showDateRangePicker(
|
|
context: context,
|
|
firstDate: DateTime(2022),
|
|
lastDate: DateTime.now(),
|
|
initialDateRange: DateTimeRange(
|
|
start: startDateAttendance ?? DateTime.now().subtract(const Duration(days: 7)),
|
|
end: endDateAttendance ?? DateTime.now(),
|
|
),
|
|
);
|
|
|
|
if (picked != null) {
|
|
startDateAttendance = picked.start;
|
|
endDateAttendance = picked.end;
|
|
|
|
await controller.fetchAttendanceLogs(
|
|
controller.selectedProjectId,
|
|
dateFrom: picked.start,
|
|
dateTo: picked.end,
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<void> fetchAttendanceLogs(
|
|
String? projectId, {
|
|
DateTime? dateFrom,
|
|
DateTime? dateTo,
|
|
}) async {
|
|
if (projectId == null) return;
|
|
|
|
isLoading.value = true; // Set loading to true before API call
|
|
final response = await ApiService.getAttendanceLogs(
|
|
int.parse(projectId),
|
|
dateFrom: dateFrom,
|
|
dateTo: dateTo,
|
|
);
|
|
isLoading.value = false; // Set loading to false after API call completes
|
|
|
|
if (response != null) {
|
|
attendanceLogs = response.map((json) => AttendanceLogModel.fromJson(json)).toList();
|
|
print("Attendance logs fetched: ${response}");
|
|
update();
|
|
} else {
|
|
print("Failed to fetch attendance logs for project $projectId.");
|
|
}
|
|
}
|
|
|
|
Future<void> fetchRegularizationLogs(
|
|
String? projectId, {
|
|
DateTime? dateFrom,
|
|
DateTime? dateTo,
|
|
}) async {
|
|
if (projectId == null) return;
|
|
|
|
isLoading.value = true; // Set loading to true before API call
|
|
final response = await ApiService.getRegularizationLogs(int.parse(projectId));
|
|
isLoading.value = false; // Set loading to false after API call completes
|
|
|
|
if (response != null) {
|
|
regularizationLogs = response
|
|
.map((json) => RegularizationLogModel.fromJson(json))
|
|
.toList();
|
|
update();
|
|
} else {
|
|
print("Failed to fetch regularization logs for project $projectId.");
|
|
}
|
|
}
|
|
|
|
Future<void> fetchLogsView(String? id) async {
|
|
if (id == null) return;
|
|
|
|
isLoading.value = true; // Set loading to true before API call
|
|
final response = await ApiService.getAttendanceLogView(int.parse(id));
|
|
isLoading.value = false; // Set loading to false after API call completes
|
|
|
|
if (response != null) {
|
|
attendenceLogsView = response
|
|
.map((json) => AttendanceLogViewModel.fromJson(json))
|
|
.toList();
|
|
update();
|
|
} else {
|
|
print("Failed to fetch regularization logs for project $id.");
|
|
}
|
|
}
|
|
}
|