From 8da8ee8371b862814639544ad732b409d60ae4a9 Mon Sep 17 00:00:00 2001 From: Vaibhav Surve Date: Fri, 25 Apr 2025 12:13:41 +0530 Subject: [PATCH] made chnages for check in and check out --- .../attendance_screen_controller.dart | 4 + lib/helpers/services/api_service.dart | 20 +-- lib/model/employee_model.dart | 14 +- lib/view/dashboard/attendanceScreen.dart | 122 +++++++++++++----- 4 files changed, 118 insertions(+), 42 deletions(-) diff --git a/lib/controller/dashboard/attendance_screen_controller.dart b/lib/controller/dashboard/attendance_screen_controller.dart index 69800f7..3f36f1f 100644 --- a/lib/controller/dashboard/attendance_screen_controller.dart +++ b/lib/controller/dashboard/attendance_screen_controller.dart @@ -79,9 +79,11 @@ class AttendanceController extends GetxController { } Future captureAndUploadAttendance( + int id, int employeeId, int projectId, { String comment = "Marked via mobile app", + required int action, }) async { try { final image = await ImagePicker().pickImage( @@ -98,6 +100,7 @@ class AttendanceController extends GetxController { ApiService.generateImageName(employeeId, employees.length + 1); return await ApiService.uploadAttendanceImage( + id, employeeId, image, position.latitude, @@ -105,6 +108,7 @@ class AttendanceController extends GetxController { imageName: imageName, projectId: projectId, comment: comment, + action: action, ); } catch (e) { print("Error capturing or uploading attendance: $e"); diff --git a/lib/helpers/services/api_service.dart b/lib/helpers/services/api_service.dart index b4c58d5..b23a487 100644 --- a/lib/helpers/services/api_service.dart +++ b/lib/helpers/services/api_service.dart @@ -106,6 +106,7 @@ class ApiService { // ===== Upload Image ===== static Future uploadAttendanceImage( + int id, int employeeId, XFile imageFile, double latitude, @@ -113,7 +114,7 @@ class ApiService { required String imageName, required int projectId, String comment = "", - int action = 0, + required int action, // action passed here }) async { final token = await _getToken(); if (token == null) return false; @@ -135,7 +136,7 @@ class ApiService { final now = DateTime.now(); final body = { - "id": null, + "id": id, "employeeId": employeeId, "projectId": projectId, "markTime": DateFormat('hh:mm a').format(now), @@ -146,21 +147,24 @@ class ApiService { "longitude": '$longitude', "image": imageObject }; - print("Upload body Image: $body"); + print("Attendance Image Upload Body: $body"); final response = await http.post( Uri.parse("$baseUrl/attendance/record-image"), headers: _headers(token), body: jsonEncode(body), ); - - print('Upload request: $baseUrl/attendance/record-image'); + print("Attendance Image Upload Response: ${response.body}"); final json = jsonDecode(response.body); - print("Upload Image response: ${response.body}"); - return response.statusCode == 200 && json['success'] == true; + if (response.statusCode == 200 && json['success'] == true) { + return true; + } else { + print("Failed to upload image. API Error: ${json['message']}"); + } } catch (e) { print("Exception during image upload: $e"); - return false; } + + return false; } // ===== Utilities ===== diff --git a/lib/model/employee_model.dart b/lib/model/employee_model.dart index f73a24c..7602c06 100644 --- a/lib/model/employee_model.dart +++ b/lib/model/employee_model.dart @@ -1,28 +1,34 @@ class EmployeeModel { final int id; + final int employeeId; final String name; final String designation; final String checkIn; final String checkOut; - final int actions; + final int activity; + int action; EmployeeModel({ required this.id, + required this.employeeId, required this.name, required this.designation, required this.checkIn, required this.checkOut, - required this.actions, + required this.action, + required this.activity, }); factory EmployeeModel.fromJson(Map json) { return EmployeeModel( - id: json['employeeId'] ?? 0, + id: json['id'] ?? 0, + employeeId: json['employeeId'] ?? 0, name: '${json['firstName']} ${json['lastName']}', designation: json['jobRoleName'] ?? '', checkIn: json['checkIn'] ?? '-', // Make sure your API returns this field checkOut: json['checkOut'] ?? '-', - actions: json['actions'] ?? 0, // Make sure your API returns this field + action: json['action'] ?? 0, // Make sure your API returns this field + activity: json['activity'] ?? 0, ); } } diff --git a/lib/view/dashboard/attendanceScreen.dart b/lib/view/dashboard/attendanceScreen.dart index 18d0d1f..08562a3 100644 --- a/lib/view/dashboard/attendanceScreen.dart +++ b/lib/view/dashboard/attendanceScreen.dart @@ -66,7 +66,7 @@ class _AttendanceScreenState extends State with UIMixin { children: [ Expanded( child: MyContainer.bordered( - padding: MySpacing.xy(4, 8), + padding: MySpacing.xy(8, 8), child: PopupMenuButton( onSelected: (value) { setState(() { @@ -122,7 +122,7 @@ class _AttendanceScreenState extends State with UIMixin { color: theme.colorScheme.onSurface, ), Icon(LucideIcons.chevron_down, - size: 16, + size: 20, color: theme.colorScheme.onSurface), ], ), @@ -219,37 +219,90 @@ class _AttendanceScreenState extends State with UIMixin { DataColumn( label: MyText.labelLarge('Actions', color: contentTheme.primary)), ], - rows: attendanceController.employees - .mapIndexed((index, employee) => DataRow(cells: [ - DataCell(MyText.bodyMedium(employee.name, fontWeight: 600)), - DataCell( - MyText.bodyMedium(employee.designation, fontWeight: 600)), - DataCell( - ElevatedButton( - onPressed: () async { - final success = await attendanceController - .captureAndUploadAttendance( - employee.id, - int.parse( - attendanceController.selectedProjectId ?? "0"), - comment: "Checked in via app", - ); + rows: attendanceController.employees.mapIndexed((index, employee) { + // Set actionText directly from employee's action + String actionText = ""; + int? activity = + employee.activity; // Assuming employee has an 'action' field - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - success - ? 'Attendence Marked successfully!' - : 'Image upload failed.', - ), - ), - ); - }, - child: const Text('Check In'), + // Set action text based on employee's activity value + if (activity == 1) { + actionText = "Check In"; + } else if (activity == 0) { + actionText = "Check Out"; + } else if (activity == 4) { + // Activity 4 logic + actionText = "Check In"; + } + + return DataRow(cells: [ + DataCell(MyText.bodyMedium(employee.name, fontWeight: 600)), + DataCell(MyText.bodyMedium(employee.designation, fontWeight: 600)), + DataCell(ElevatedButton( + onPressed: () async { + if (attendanceController.selectedProjectId == null) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text("Please select a project first")), + ); + return; + } + + // Determine the updated action based on current activity + int updatedAction; + String actionText; + + if (activity == 0 || activity == 4) { + // The user is currently checked in (activity == 0), so they need to check out + updatedAction = 0; + actionText = "Check In"; + } else { + // The user is currently checked out (activity == 1), so they need to check in + updatedAction = 1; + actionText = "Check Out"; + } + + // Call the method to capture attendance with the updated action + final success = + await attendanceController.captureAndUploadAttendance( + employee.id, // Pass the employee's ID + employee.employeeId, + + int.parse(attendanceController + .selectedProjectId!), // Pass the selected project ID + comment: actionText, // Action text (Check In / Check Out) + action: updatedAction, + ); + + // Show success or failure message + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + success + ? 'Attendance marked successfully!' + : 'Image upload failed.', ), ), - ])) - .toList(), + ); + if (success) { + // Fetch the updated list of employees and logs after the attendance upload + attendanceController.fetchEmployeesByProject( + attendanceController.selectedProjectId!); + attendanceController.fetchAttendanceLogs( + attendanceController.selectedProjectId!); + // You can add more fetch calls if necessary, such as regularization logs. + } + }, + style: ElevatedButton.styleFrom( + padding: EdgeInsets.symmetric( + vertical: 4, horizontal: 6), // Adjust padding + minimumSize: Size(60, 20), // Adjust minimum size for the button + textStyle: TextStyle(fontSize: 12), // Smaller font size + ), + child: Text( + activity == 0 || activity == 4 ? 'Check In' : 'Check Out'), + )), + ]); + }).toList(), ), ); } @@ -333,6 +386,15 @@ class _AttendanceScreenState extends State with UIMixin { )), DataCell( ElevatedButton( + style: ElevatedButton.styleFrom( + padding: EdgeInsets.symmetric( + vertical: 4, + horizontal: 6), // Adjust padding + minimumSize: + Size(60, 20), // Adjust minimum size + textStyle: TextStyle( + fontSize: 12), // Smaller font size + ), onPressed: () async { // Call fetchLogsView to load the log data await attendanceController.fetchLogsView(log.id