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(
|
Future<bool> captureAndUploadAttendance(
|
||||||
|
int id,
|
||||||
int employeeId,
|
int employeeId,
|
||||||
int projectId, {
|
int projectId, {
|
||||||
String comment = "Marked via mobile app",
|
String comment = "Marked via mobile app",
|
||||||
|
required int action,
|
||||||
}) async {
|
}) async {
|
||||||
try {
|
try {
|
||||||
final image = await ImagePicker().pickImage(
|
final image = await ImagePicker().pickImage(
|
||||||
@ -98,6 +100,7 @@ class AttendanceController extends GetxController {
|
|||||||
ApiService.generateImageName(employeeId, employees.length + 1);
|
ApiService.generateImageName(employeeId, employees.length + 1);
|
||||||
|
|
||||||
return await ApiService.uploadAttendanceImage(
|
return await ApiService.uploadAttendanceImage(
|
||||||
|
id,
|
||||||
employeeId,
|
employeeId,
|
||||||
image,
|
image,
|
||||||
position.latitude,
|
position.latitude,
|
||||||
@ -105,6 +108,7 @@ class AttendanceController extends GetxController {
|
|||||||
imageName: imageName,
|
imageName: imageName,
|
||||||
projectId: projectId,
|
projectId: projectId,
|
||||||
comment: comment,
|
comment: comment,
|
||||||
|
action: action,
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print("Error capturing or uploading attendance: $e");
|
print("Error capturing or uploading attendance: $e");
|
||||||
|
@ -106,6 +106,7 @@ class ApiService {
|
|||||||
// ===== Upload Image =====
|
// ===== Upload Image =====
|
||||||
|
|
||||||
static Future<bool> uploadAttendanceImage(
|
static Future<bool> uploadAttendanceImage(
|
||||||
|
int id,
|
||||||
int employeeId,
|
int employeeId,
|
||||||
XFile imageFile,
|
XFile imageFile,
|
||||||
double latitude,
|
double latitude,
|
||||||
@ -113,7 +114,7 @@ class ApiService {
|
|||||||
required String imageName,
|
required String imageName,
|
||||||
required int projectId,
|
required int projectId,
|
||||||
String comment = "",
|
String comment = "",
|
||||||
int action = 0,
|
required int action, // action passed here
|
||||||
}) async {
|
}) async {
|
||||||
final token = await _getToken();
|
final token = await _getToken();
|
||||||
if (token == null) return false;
|
if (token == null) return false;
|
||||||
@ -135,7 +136,7 @@ class ApiService {
|
|||||||
final now = DateTime.now();
|
final now = DateTime.now();
|
||||||
|
|
||||||
final body = {
|
final body = {
|
||||||
"id": null,
|
"id": id,
|
||||||
"employeeId": employeeId,
|
"employeeId": employeeId,
|
||||||
"projectId": projectId,
|
"projectId": projectId,
|
||||||
"markTime": DateFormat('hh:mm a').format(now),
|
"markTime": DateFormat('hh:mm a').format(now),
|
||||||
@ -146,21 +147,24 @@ class ApiService {
|
|||||||
"longitude": '$longitude',
|
"longitude": '$longitude',
|
||||||
"image": imageObject
|
"image": imageObject
|
||||||
};
|
};
|
||||||
print("Upload body Image: $body");
|
print("Attendance Image Upload Body: $body");
|
||||||
final response = await http.post(
|
final response = await http.post(
|
||||||
Uri.parse("$baseUrl/attendance/record-image"),
|
Uri.parse("$baseUrl/attendance/record-image"),
|
||||||
headers: _headers(token),
|
headers: _headers(token),
|
||||||
body: jsonEncode(body),
|
body: jsonEncode(body),
|
||||||
);
|
);
|
||||||
|
print("Attendance Image Upload Response: ${response.body}");
|
||||||
print('Upload request: $baseUrl/attendance/record-image');
|
|
||||||
final json = jsonDecode(response.body);
|
final json = jsonDecode(response.body);
|
||||||
print("Upload Image response: ${response.body}");
|
if (response.statusCode == 200 && json['success'] == true) {
|
||||||
return response.statusCode == 200 && json['success'] == true;
|
return true;
|
||||||
|
} else {
|
||||||
|
print("Failed to upload image. API Error: ${json['message']}");
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print("Exception during image upload: $e");
|
print("Exception during image upload: $e");
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===== Utilities =====
|
// ===== Utilities =====
|
||||||
|
@ -1,28 +1,34 @@
|
|||||||
class EmployeeModel {
|
class EmployeeModel {
|
||||||
final int id;
|
final int id;
|
||||||
|
final int employeeId;
|
||||||
final String name;
|
final String name;
|
||||||
final String designation;
|
final String designation;
|
||||||
final String checkIn;
|
final String checkIn;
|
||||||
final String checkOut;
|
final String checkOut;
|
||||||
final int actions;
|
final int activity;
|
||||||
|
int action;
|
||||||
|
|
||||||
EmployeeModel({
|
EmployeeModel({
|
||||||
required this.id,
|
required this.id,
|
||||||
|
required this.employeeId,
|
||||||
required this.name,
|
required this.name,
|
||||||
required this.designation,
|
required this.designation,
|
||||||
required this.checkIn,
|
required this.checkIn,
|
||||||
required this.checkOut,
|
required this.checkOut,
|
||||||
required this.actions,
|
required this.action,
|
||||||
|
required this.activity,
|
||||||
});
|
});
|
||||||
|
|
||||||
factory EmployeeModel.fromJson(Map<String, dynamic> json) {
|
factory EmployeeModel.fromJson(Map<String, dynamic> json) {
|
||||||
return EmployeeModel(
|
return EmployeeModel(
|
||||||
id: json['employeeId'] ?? 0,
|
id: json['id'] ?? 0,
|
||||||
|
employeeId: json['employeeId'] ?? 0,
|
||||||
name: '${json['firstName']} ${json['lastName']}',
|
name: '${json['firstName']} ${json['lastName']}',
|
||||||
designation: json['jobRoleName'] ?? '',
|
designation: json['jobRoleName'] ?? '',
|
||||||
checkIn: json['checkIn'] ?? '-', // Make sure your API returns this field
|
checkIn: json['checkIn'] ?? '-', // Make sure your API returns this field
|
||||||
checkOut: json['checkOut'] ?? '-',
|
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: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: MyContainer.bordered(
|
child: MyContainer.bordered(
|
||||||
padding: MySpacing.xy(4, 8),
|
padding: MySpacing.xy(8, 8),
|
||||||
child: PopupMenuButton<String>(
|
child: PopupMenuButton<String>(
|
||||||
onSelected: (value) {
|
onSelected: (value) {
|
||||||
setState(() {
|
setState(() {
|
||||||
@ -122,7 +122,7 @@ class _AttendanceScreenState extends State<AttendanceScreen> with UIMixin {
|
|||||||
color: theme.colorScheme.onSurface,
|
color: theme.colorScheme.onSurface,
|
||||||
),
|
),
|
||||||
Icon(LucideIcons.chevron_down,
|
Icon(LucideIcons.chevron_down,
|
||||||
size: 16,
|
size: 20,
|
||||||
color: theme.colorScheme.onSurface),
|
color: theme.colorScheme.onSurface),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -219,37 +219,90 @@ class _AttendanceScreenState extends State<AttendanceScreen> with UIMixin {
|
|||||||
DataColumn(
|
DataColumn(
|
||||||
label: MyText.labelLarge('Actions', color: contentTheme.primary)),
|
label: MyText.labelLarge('Actions', color: contentTheme.primary)),
|
||||||
],
|
],
|
||||||
rows: attendanceController.employees
|
rows: attendanceController.employees.mapIndexed((index, employee) {
|
||||||
.mapIndexed((index, employee) => DataRow(cells: [
|
// Set actionText directly from employee's action
|
||||||
DataCell(MyText.bodyMedium(employee.name, fontWeight: 600)),
|
String actionText = "";
|
||||||
DataCell(
|
int? activity =
|
||||||
MyText.bodyMedium(employee.designation, fontWeight: 600)),
|
employee.activity; // Assuming employee has an 'action' field
|
||||||
DataCell(
|
|
||||||
ElevatedButton(
|
|
||||||
onPressed: () async {
|
|
||||||
final success = await attendanceController
|
|
||||||
.captureAndUploadAttendance(
|
|
||||||
employee.id,
|
|
||||||
int.parse(
|
|
||||||
attendanceController.selectedProjectId ?? "0"),
|
|
||||||
comment: "Checked in via app",
|
|
||||||
);
|
|
||||||
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
// Set action text based on employee's activity value
|
||||||
SnackBar(
|
if (activity == 1) {
|
||||||
content: Text(
|
actionText = "Check In";
|
||||||
success
|
} else if (activity == 0) {
|
||||||
? 'Attendence Marked successfully!'
|
actionText = "Check Out";
|
||||||
: 'Image upload failed.',
|
} else if (activity == 4) {
|
||||||
),
|
// Activity 4 logic
|
||||||
),
|
actionText = "Check In";
|
||||||
);
|
}
|
||||||
},
|
|
||||||
child: const Text('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(
|
DataCell(
|
||||||
ElevatedButton(
|
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 {
|
onPressed: () async {
|
||||||
// Call fetchLogsView to load the log data
|
// Call fetchLogsView to load the log data
|
||||||
await attendanceController.fetchLogsView(log.id
|
await attendanceController.fetchLogsView(log.id
|
||||||
|
Loading…
x
Reference in New Issue
Block a user