diff --git a/lib/view/dashboard/attendanceScreen.dart b/lib/view/dashboard/attendanceScreen.dart index 36d1042..e0ce957 100644 --- a/lib/view/dashboard/attendanceScreen.dart +++ b/lib/view/dashboard/attendanceScreen.dart @@ -279,75 +279,86 @@ class _AttendanceScreenState extends State with UIMixin { .uploadingStates[employee.employeeId]?.value ?? false; final controller = attendanceController; - return SizedBox( - width: 90, - height: 25, - child: ElevatedButton( - onPressed: isUploading - ? null - : () async { - controller.uploadingStates[employee.employeeId] = - RxBool(true); - if (controller.selectedProjectId == null) { - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text("Please select a project first")), + return ConstrainedBox( + constraints: const BoxConstraints(minWidth: 100, maxWidth: 140), + child: SizedBox( + height: 30, + child: ElevatedButton( + onPressed: isUploading + ? null + : () async { + controller.uploadingStates[employee.employeeId] = + RxBool(true); + if (controller.selectedProjectId == null) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: + Text("Please select a project first")), + ); + controller.uploadingStates[employee.employeeId] = + RxBool(false); + return; + } + final updatedAction = + (activity == 0 || activity == 4) ? 0 : 1; + final actionText = (updatedAction == 0) + ? ButtonActions.checkIn + : ButtonActions.checkOut; + final success = + await controller.captureAndUploadAttendance( + employee.id, + employee.employeeId, + controller.selectedProjectId!, + comment: actionText, + action: updatedAction, ); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(success + ? 'Attendance marked successfully!' + : 'Image upload failed.'), + ), + ); + controller.uploadingStates[employee.employeeId] = RxBool(false); - return; - } - final updatedAction = - (activity == 0 || activity == 4) ? 0 : 1; - final actionText = (updatedAction == 0) - ? ButtonActions.checkIn - : ButtonActions.checkOut; - final success = - await controller.captureAndUploadAttendance( - employee.id, - employee.employeeId, - controller.selectedProjectId!, - comment: actionText, - action: updatedAction, - ); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(success - ? 'Attendance marked successfully!' - : 'Image upload failed.'), + + if (success) { + await Future.wait([ + controller.fetchEmployeesByProject( + controller.selectedProjectId!), + controller.fetchAttendanceLogs( + controller.selectedProjectId!), + controller.fetchProjectData( + controller.selectedProjectId!), + ]); + controller.update(); + } + }, + style: ElevatedButton.styleFrom( + backgroundColor: AttendanceActionColors.colors[buttonText], + textStyle: const TextStyle(fontSize: 12), + padding: const EdgeInsets.symmetric(horizontal: 12), + ), + child: isUploading + ? const SizedBox( + width: 16, + height: 16, + child: CircularProgressIndicator( + strokeWidth: 2, + valueColor: + AlwaysStoppedAnimation(Colors.white), + ), + ) + : FittedBox( + fit: BoxFit.scaleDown, + child: Text( + buttonText, + overflow: TextOverflow.ellipsis, + style: const TextStyle(fontSize: 12), ), - ); - - controller.uploadingStates[employee.employeeId] = - RxBool(false); - - if (success) { - await Future.wait([ - controller.fetchEmployeesByProject( - controller.selectedProjectId!), - controller.fetchAttendanceLogs( - controller.selectedProjectId!), - controller.fetchProjectData( - controller.selectedProjectId!), - ]); - controller.update(); - } - }, - style: ElevatedButton.styleFrom( - backgroundColor: AttendanceActionColors.colors[buttonText], - textStyle: const TextStyle(fontSize: 12), - ), - child: isUploading - ? const SizedBox( - width: 16, - height: 16, - child: CircularProgressIndicator( - strokeWidth: 2, - valueColor: - AlwaysStoppedAnimation(Colors.white), ), - ) - : Text(buttonText), + ), ), ); }), @@ -645,77 +656,100 @@ class _AttendanceScreenState extends State with UIMixin { isApprovedButNotToday: isApprovedButNotToday, ); - return SizedBox( - width: 90, - height: 25, - child: ElevatedButton( - onPressed: isButtonDisabled - ? null - : () async { - attendanceController.uploadingStates[uniqueLogKey] = - RxBool(true); - - if (attendanceController.selectedProjectId == null) { - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: - Text("Please select a project first")), - ); + return ConstrainedBox( + constraints: const BoxConstraints(minWidth: 100, maxWidth: 150), + child: SizedBox( + height: 30, + child: ElevatedButton( + onPressed: isButtonDisabled + ? null + : () async { attendanceController.uploadingStates[uniqueLogKey] = - RxBool(false); - return; - } + RxBool(true); - int updatedAction; - String actionText; - bool imageCapture = true; + if (attendanceController.selectedProjectId == + null) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: + Text("Please select a project first"), + ), + ); + attendanceController + .uploadingStates[uniqueLogKey] = + RxBool(false); + return; + } - switch (log.activity) { - case 0: - updatedAction = 0; - actionText = ButtonActions.checkIn; - break; - case 1: - if (log.checkOut == null && - AttendanceButtonHelper.isOlderThanDays( - log.checkIn, 2)) { + int updatedAction; + String actionText; + bool imageCapture = true; + + switch (log.activity) { + case 0: + updatedAction = 0; + actionText = ButtonActions.checkIn; + break; + case 1: + if (log.checkOut == null && + AttendanceButtonHelper.isOlderThanDays( + log.checkIn, 2)) { + updatedAction = 2; + actionText = ButtonActions.requestRegularize; + imageCapture = false; + } else if (log.checkOut != null && + AttendanceButtonHelper.isOlderThanDays( + log.checkOut, 2)) { + updatedAction = 2; + actionText = ButtonActions.requestRegularize; + } else { + updatedAction = 1; + actionText = ButtonActions.checkOut; + } + break; + case 2: updatedAction = 2; actionText = ButtonActions.requestRegularize; - imageCapture = false; - } else if (log.checkOut != null && - AttendanceButtonHelper.isOlderThanDays( - log.checkOut, 2)) { - updatedAction = 2; - actionText = ButtonActions.requestRegularize; - } else { - updatedAction = 1; - actionText = ButtonActions.checkOut; + break; + case 4: + updatedAction = isTodayApproved ? 0 : 0; + actionText = ButtonActions.checkIn; + break; + default: + updatedAction = 0; + actionText = "Unknown Action"; + break; + } + + bool success = false; + if (actionText == ButtonActions.requestRegularize) { + final selectedTime = + await showTimePickerForRegularization( + context: context, + checkInTime: log.checkIn!, + ); + if (selectedTime != null) { + final formattedSelectedTime = + DateFormat("hh:mm a").format(selectedTime); + success = await attendanceController + .captureAndUploadAttendance( + log.id, + log.employeeId, + attendanceController.selectedProjectId!, + comment: actionText, + action: updatedAction, + imageCapture: imageCapture, + markTime: formattedSelectedTime, + ); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(success + ? '${actionText.toLowerCase()} marked successfully!' + : 'Failed to ${actionText.toLowerCase()}'), + ), + ); } - break; - case 2: - updatedAction = 2; - actionText = ButtonActions.requestRegularize; - break; - case 4: - updatedAction = isTodayApproved ? 0 : 0; - actionText = ButtonActions.checkIn; - break; - default: - updatedAction = 0; - actionText = "Unknown Action"; - break; - } - - bool success = false; - if (actionText == ButtonActions.requestRegularize) { - final selectedTime = - await showTimePickerForRegularization( - context: context, - checkInTime: log.checkIn!, - ); - if (selectedTime != null) { - final formattedSelectedTime = - DateFormat("hh:mm a").format(selectedTime); + } else { success = await attendanceController .captureAndUploadAttendance( log.id, @@ -724,82 +758,70 @@ class _AttendanceScreenState extends State with UIMixin { comment: actionText, action: updatedAction, imageCapture: imageCapture, - markTime: formattedSelectedTime, ); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(success ? '${actionText.toLowerCase()} marked successfully!' - : 'Failed to ${actionText.toLowerCase()}.'), + : 'Failed to ${actionText.toLowerCase()}'), ), ); } - } else { - success = await attendanceController - .captureAndUploadAttendance( - log.id, - log.employeeId, - attendanceController.selectedProjectId!, - comment: actionText, - action: updatedAction, - imageCapture: imageCapture, - ); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(success - ? '${actionText.toLowerCase()} marked successfully!' - : 'Failed to ${actionText.toLowerCase()}.'), - ), - ); - } - attendanceController.uploadingStates[uniqueLogKey] = - RxBool(false); + attendanceController.uploadingStates[uniqueLogKey] = + RxBool(false); - if (success) { - attendanceController.fetchEmployeesByProject( - attendanceController.selectedProjectId!); - attendanceController.fetchAttendanceLogs( - attendanceController.selectedProjectId!); - await attendanceController.fetchRegularizationLogs( - attendanceController.selectedProjectId!); - await attendanceController.fetchProjectData( - attendanceController.selectedProjectId!); - attendanceController.update(); - } - }, - style: ElevatedButton.styleFrom( - backgroundColor: AttendanceButtonHelper.getButtonColor( - isYesterday: isYesterday, - isTodayApproved: isTodayApproved, - activity: log.activity, + if (success) { + attendanceController.fetchEmployeesByProject( + attendanceController.selectedProjectId!); + attendanceController.fetchAttendanceLogs( + attendanceController.selectedProjectId!); + await attendanceController + .fetchRegularizationLogs( + attendanceController.selectedProjectId!); + await attendanceController.fetchProjectData( + attendanceController.selectedProjectId!); + attendanceController.update(); + } + }, + style: ElevatedButton.styleFrom( + backgroundColor: AttendanceButtonHelper.getButtonColor( + isYesterday: isYesterday, + isTodayApproved: isTodayApproved, + activity: log.activity, + ), + padding: const EdgeInsets.symmetric( + vertical: 4, horizontal: 6), + textStyle: const TextStyle(fontSize: 12), ), - padding: - const EdgeInsets.symmetric(vertical: 4, horizontal: 6), - textStyle: const TextStyle(fontSize: 12), + child: isUploading + ? const SizedBox( + width: 16, + height: 16, + child: CircularProgressIndicator( + strokeWidth: 2, + valueColor: + AlwaysStoppedAnimation(Colors.white), + ), + ) + : FittedBox( + fit: BoxFit.scaleDown, + child: Text( + AttendanceButtonHelper.getButtonText( + activity: log.activity, + checkIn: log.checkIn, + checkOut: log.checkOut, + isTodayApproved: isTodayApproved, + ), + overflow: TextOverflow.ellipsis, + style: const TextStyle(fontSize: 12), + ), + ), ), - child: isUploading - ? const SizedBox( - width: 16, - height: 16, - child: CircularProgressIndicator( - strokeWidth: 2, - valueColor: - AlwaysStoppedAnimation(Colors.white), - ), - ) - : Text( - AttendanceButtonHelper.getButtonText( - activity: log.activity, - checkIn: log.checkIn, - checkOut: log.checkOut, - isTodayApproved: isTodayApproved, - ), - ), ), ); }), - ) + ), ])); } }); @@ -917,129 +939,165 @@ class _AttendanceScreenState extends State with UIMixin { Row( children: [ // Approve Button - ElevatedButton( - onPressed: isUploading // Disable button if uploading - ? null - : () async { - if (attendanceController.selectedProjectId == null) { - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text("Please select a project first")), - ); - return; - } + ConstrainedBox( + constraints: const BoxConstraints(minWidth: 70, maxWidth: 120), + child: SizedBox( + height: 30, + child: ElevatedButton( + onPressed: isUploading + ? null + : () async { + if (attendanceController.selectedProjectId == + null) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: + Text("Please select a project first")), + ); + return; + } - attendanceController.uploadingStates[uniqueLogKey] - ?.value = true; // Start loading - final success = await attendanceController - .captureAndUploadAttendance( - log.id, - log.employeeId, - attendanceController.selectedProjectId!, - comment: "Accepted", - action: 4, // Approve action - imageCapture: false, - ); + attendanceController + .uploadingStates[uniqueLogKey]?.value = true; - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(success - ? 'Approval marked successfully!' - : 'Failed to mark approval.')), - ); + final success = await attendanceController + .captureAndUploadAttendance( + log.id, + log.employeeId, + attendanceController.selectedProjectId!, + comment: "Accepted", + action: 4, + imageCapture: false, + ); - if (success) { - attendanceController.fetchEmployeesByProject( - attendanceController.selectedProjectId!); - attendanceController.fetchAttendanceLogs( - attendanceController.selectedProjectId!); - await attendanceController.fetchRegularizationLogs( - attendanceController.selectedProjectId!); - await attendanceController.fetchProjectData( - attendanceController.selectedProjectId!); - } + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(success + ? 'Approval marked successfully!' + : 'Failed to mark approval.'), + ), + ); - attendanceController.uploadingStates[uniqueLogKey] - ?.value = false; // End loading - }, - style: ElevatedButton.styleFrom( - backgroundColor: - AttendanceActionColors.colors[ButtonActions.approve], - padding: - const EdgeInsets.symmetric(vertical: 4, horizontal: 6), - minimumSize: const Size(60, 20), - textStyle: const TextStyle(fontSize: 12), + if (success) { + attendanceController.fetchEmployeesByProject( + attendanceController.selectedProjectId!); + attendanceController.fetchAttendanceLogs( + attendanceController.selectedProjectId!); + await attendanceController + .fetchRegularizationLogs( + attendanceController.selectedProjectId!); + await attendanceController.fetchProjectData( + attendanceController.selectedProjectId!); + } + + attendanceController + .uploadingStates[uniqueLogKey]?.value = false; + }, + style: ElevatedButton.styleFrom( + backgroundColor: + AttendanceActionColors.colors[ButtonActions.approve], + padding: const EdgeInsets.symmetric( + vertical: 4, horizontal: 6), + minimumSize: const Size(60, 20), + textStyle: const TextStyle(fontSize: 12), + ), + child: isUploading + ? const SizedBox( + width: 16, + height: 16, + child: CircularProgressIndicator(strokeWidth: 2), + ) + : FittedBox( + fit: BoxFit.scaleDown, + child: const Text( + "Approve", + overflow: TextOverflow.ellipsis, + ), + ), + ), ), - child: isUploading - ? const CircularProgressIndicator( - strokeWidth: - 2) // Show loading indicator while uploading - : const Text("Approve"), ), - // Space between buttons const SizedBox(width: 8), // Reject Button - ElevatedButton( - onPressed: isUploading // Disable button if uploading - ? null - : () async { - if (attendanceController.selectedProjectId == null) { - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text("Please select a project first")), - ); - return; - } + ConstrainedBox( + constraints: const BoxConstraints(minWidth: 70, maxWidth: 120), + child: SizedBox( + height: 30, + child: ElevatedButton( + onPressed: isUploading + ? null + : () async { + if (attendanceController.selectedProjectId == + null) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: + Text("Please select a project first")), + ); + return; + } - attendanceController.uploadingStates[uniqueLogKey] - ?.value = true; // Start loading + attendanceController + .uploadingStates[uniqueLogKey]?.value = true; - final success = await attendanceController - .captureAndUploadAttendance( - log.id, - log.employeeId, - attendanceController.selectedProjectId!, - comment: "Rejected", - action: 5, // Reject action - imageCapture: false, - ); + final success = await attendanceController + .captureAndUploadAttendance( + log.id, + log.employeeId, + attendanceController.selectedProjectId!, + comment: "Rejected", + action: 5, + imageCapture: false, + ); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(success - ? 'Attendance marked as Rejected!' - : 'Failed to mark attendance.')), - ); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(success + ? 'Attendance marked as Rejected!' + : 'Failed to mark attendance.'), + ), + ); - if (success) { - attendanceController.fetchEmployeesByProject( - attendanceController.selectedProjectId!); - attendanceController.fetchAttendanceLogs( - attendanceController.selectedProjectId!); - await attendanceController.fetchRegularizationLogs( - attendanceController.selectedProjectId!); - await attendanceController.fetchProjectData( - attendanceController.selectedProjectId!); - } + if (success) { + attendanceController.fetchEmployeesByProject( + attendanceController.selectedProjectId!); + attendanceController.fetchAttendanceLogs( + attendanceController.selectedProjectId!); + await attendanceController + .fetchRegularizationLogs( + attendanceController.selectedProjectId!); + await attendanceController.fetchProjectData( + attendanceController.selectedProjectId!); + } - attendanceController.uploadingStates[uniqueLogKey] - ?.value = false; // End loading - }, - style: ElevatedButton.styleFrom( - backgroundColor: - AttendanceActionColors.colors[ButtonActions.reject], - padding: - const EdgeInsets.symmetric(vertical: 4, horizontal: 6), - minimumSize: const Size(60, 20), - textStyle: const TextStyle(fontSize: 12), + attendanceController + .uploadingStates[uniqueLogKey]?.value = false; + }, + style: ElevatedButton.styleFrom( + backgroundColor: + AttendanceActionColors.colors[ButtonActions.reject], + padding: const EdgeInsets.symmetric( + vertical: 4, horizontal: 6), + minimumSize: const Size(60, 20), + textStyle: const TextStyle(fontSize: 12), + ), + child: isUploading + ? const SizedBox( + width: 16, + height: 16, + child: CircularProgressIndicator(strokeWidth: 2), + ) + : FittedBox( + fit: BoxFit.scaleDown, + child: const Text( + "Reject", + overflow: TextOverflow.ellipsis, + ), + ), + ), ), - child: isUploading - ? const CircularProgressIndicator( - strokeWidth: - 2) // Show loading indicator while uploading - : const Text("Reject"), ), ], ),