made chnages for check in and check out
This commit is contained in:
parent
7936072b74
commit
8da8ee8371
@ -79,9 +79,11 @@ class AttendanceController extends GetxController {
|
||||
}
|
||||
|
||||
Future<bool> 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");
|
||||
|
@ -106,6 +106,7 @@ class ApiService {
|
||||
// ===== Upload Image =====
|
||||
|
||||
static Future<bool> 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 =====
|
||||
|
@ -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<String, dynamic> 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,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ class _AttendanceScreenState extends State<AttendanceScreen> with UIMixin {
|
||||
children: [
|
||||
Expanded(
|
||||
child: MyContainer.bordered(
|
||||
padding: MySpacing.xy(4, 8),
|
||||
padding: MySpacing.xy(8, 8),
|
||||
child: PopupMenuButton<String>(
|
||||
onSelected: (value) {
|
||||
setState(() {
|
||||
@ -122,7 +122,7 @@ class _AttendanceScreenState extends State<AttendanceScreen> 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<AttendanceScreen> 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<AttendanceScreen> 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
|
||||
|
Loading…
x
Reference in New Issue
Block a user