228 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
			
		
		
	
	
			228 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
| import 'package:flutter/material.dart';
 | |
| import 'package:get/get.dart';
 | |
| import 'package:marco/helpers/theme/app_theme.dart';
 | |
| import 'package:marco/helpers/utils/mixins/ui_mixin.dart';
 | |
| import 'package:marco/helpers/utils/my_shadow.dart';
 | |
| import 'package:marco/helpers/widgets/my_breadcrumb.dart';
 | |
| import 'package:marco/helpers/widgets/my_breadcrumb_item.dart';
 | |
| import 'package:marco/helpers/widgets/my_card.dart';
 | |
| import 'package:marco/helpers/widgets/my_container.dart';
 | |
| import 'package:marco/helpers/widgets/my_flex.dart';
 | |
| import 'package:marco/helpers/widgets/my_flex_item.dart';
 | |
| import 'package:marco/helpers/widgets/my_spacing.dart';
 | |
| import 'package:marco/helpers/widgets/my_text.dart';
 | |
| import 'package:marco/view/layouts/layout.dart';
 | |
| import 'package:marco/controller/dashboard/attendance_screen_controller.dart';
 | |
| import 'package:marco/controller/permission_controller.dart';
 | |
| import 'package:intl/intl.dart';
 | |
| import 'package:marco/model/attendance/attendence_action_button.dart';
 | |
| import 'package:marco/helpers/widgets/avatar.dart';
 | |
| import 'package:marco/model/attendance/log_details_view.dart';
 | |
| 
 | |
| class AttendenceLogScreen extends StatefulWidget {
 | |
|   const AttendenceLogScreen({super.key});
 | |
| 
 | |
|   @override
 | |
|   State<AttendenceLogScreen> createState() => _AttendenceLogScreenState();
 | |
| }
 | |
| 
 | |
| class _AttendenceLogScreenState extends State<AttendenceLogScreen>
 | |
|     with UIMixin {
 | |
|   final AttendanceController attendanceController =
 | |
|       Get.put(AttendanceController());
 | |
|   final PermissionController permissionController =
 | |
|       Get.put(PermissionController());
 | |
|   @override
 | |
|   Widget build(BuildContext context) {
 | |
|     return Layout(
 | |
|       child: GetBuilder(
 | |
|         init: attendanceController,
 | |
|         tag: 'attendence_controller',
 | |
|         builder: (controller) {
 | |
|           return Column(
 | |
|             crossAxisAlignment: CrossAxisAlignment.start,
 | |
|             children: [
 | |
|               Padding(
 | |
|                 padding: MySpacing.x(flexSpacing),
 | |
|                 child: Row(
 | |
|                   mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | |
|                   children: [
 | |
|                     MyText.titleMedium("Attendence",
 | |
|                         fontSize: 18, fontWeight: 600),
 | |
|                     MyBreadcrumb(
 | |
|                       children: [
 | |
|                         MyBreadcrumbItem(name: 'Dashboard'),
 | |
|                         MyBreadcrumbItem(name: 'Attendence', active: true),
 | |
|                       ],
 | |
|                     ),
 | |
|                   ],
 | |
|                 ),
 | |
|               ),
 | |
|               MySpacing.height(flexSpacing),
 | |
|               Padding(
 | |
|                 padding: MySpacing.x(flexSpacing / 2),
 | |
|                 child: MyFlex(children: [
 | |
|                   MyFlexItem(sizes: 'lg-12 md-12 sm-12', child: employeeLog()),
 | |
|                 ]),
 | |
|               )
 | |
|             ],
 | |
|           );
 | |
|         },
 | |
|       ),
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   Widget employeeLog() {
 | |
|     return MyCard.bordered(
 | |
|       borderRadiusAll: 4,
 | |
|       border: Border.all(color: Colors.grey.withOpacity(0.2)),
 | |
|       shadow: MyShadow(elevation: 1, position: MyShadowPosition.bottom),
 | |
|       paddingAll: 8,
 | |
|       child: Column(
 | |
|         crossAxisAlignment: CrossAxisAlignment.start,
 | |
|         children: [
 | |
|           attendanceController.employees.isEmpty
 | |
|               ? MyText.bodySmall("No Employees Assigned to This Project",
 | |
|                   fontWeight: 600)
 | |
|               : Column(
 | |
|                   children: List.generate(attendanceController.employees.length,
 | |
|                       (index) {
 | |
|                     final employee = attendanceController.employees[index];
 | |
|                     return Column(
 | |
|                       children: [
 | |
|                         Padding(
 | |
|                           padding: const EdgeInsets.only(bottom: 16.0),
 | |
|                           child: MyContainer(
 | |
|                             paddingAll: 12,
 | |
|                             child: Row(
 | |
|                               crossAxisAlignment: CrossAxisAlignment.start,
 | |
|                               children: [
 | |
|                                 Column(
 | |
|                                   mainAxisAlignment: MainAxisAlignment.start,
 | |
|                                   children: [
 | |
|                                     Avatar(
 | |
|                                       firstName: employee.firstName,
 | |
|                                       lastName: employee.lastName,
 | |
|                                       size: 31,
 | |
|                                     )
 | |
|                                   ],
 | |
|                                 ),
 | |
|                                 MySpacing.width(16),
 | |
|                                 Expanded(
 | |
|                                   child: Column(
 | |
|                                     crossAxisAlignment:
 | |
|                                         CrossAxisAlignment.start,
 | |
|                                     children: [
 | |
|                                       Row(
 | |
|                                         children: [
 | |
|                                           Expanded(
 | |
|                                             child: MyText.bodyMedium(
 | |
|                                               '${employee.name} '
 | |
|                                               ' (${employee.designation})',
 | |
|                                               fontWeight: 600,
 | |
|                                               maxLines: null,
 | |
|                                               overflow: TextOverflow.visible,
 | |
|                                               softWrap: true,
 | |
|                                             ),
 | |
|                                           ),
 | |
|                                         ],
 | |
|                                       ),
 | |
|                                       MySpacing.height(8),
 | |
|                                       Row(
 | |
|                                         children: [
 | |
|                                           MyText.bodySmall("In: ",
 | |
|                                               fontWeight: 600),
 | |
|                                           MyText.bodySmall(
 | |
|                                             employee.checkIn != null
 | |
|                                                 ? DateFormat('hh:mm a')
 | |
|                                                     .format(employee.checkIn!)
 | |
|                                                 : '--',
 | |
|                                             fontWeight: 600,
 | |
|                                           ),
 | |
|                                           MySpacing.width(16),
 | |
|                                           MyText.bodySmall("Out: ",
 | |
|                                               fontWeight: 600),
 | |
|                                           MyText.bodySmall(
 | |
|                                             employee.checkOut != null
 | |
|                                                 ? DateFormat('hh:mm a')
 | |
|                                                     .format(employee.checkOut!)
 | |
|                                                 : '--',
 | |
|                                             fontWeight: 600,
 | |
|                                           ),
 | |
|                                         ],
 | |
|                                       ),
 | |
|                                       MySpacing.height(12),
 | |
|                                       Row(
 | |
|                                         children: [
 | |
|                                           AttendanceLogViewButton(
 | |
|                                             employee: employee,
 | |
|                                             attendanceController:
 | |
|                                                 attendanceController,
 | |
|                                           ),
 | |
|                                           MySpacing.width(8),
 | |
|                                           AttendanceActionButton(
 | |
|                                             employee: employee,
 | |
|                                             attendanceController:
 | |
|                                                 attendanceController,
 | |
|                                       
 | |
|                                           ),
 | |
|                                         ],
 | |
|                                       ),
 | |
|                                     ],
 | |
|                                   ),
 | |
|                                 ),
 | |
|                               ],
 | |
|                             ),
 | |
|                           ),
 | |
|                         ),
 | |
|                         if (index != attendanceController.employees.length - 1)
 | |
|                           Padding(
 | |
|                             padding: const EdgeInsets.symmetric(),
 | |
|                             child: Divider(
 | |
|                               color: Colors.grey.withOpacity(0.3),
 | |
|                               thickness: 1,
 | |
|                               height: 1,
 | |
|                             ),
 | |
|                           ),
 | |
|                       ],
 | |
|                     );
 | |
|                   }),
 | |
|                 ),
 | |
|         ],
 | |
|       ),
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   Future<DateTime?> showTimePickerForRegularization({
 | |
|     required BuildContext context,
 | |
|     required DateTime checkInTime,
 | |
|   }) async {
 | |
|     final pickedTime = await showTimePicker(
 | |
|       context: context,
 | |
|       initialTime: TimeOfDay.fromDateTime(DateTime.now()),
 | |
|     );
 | |
| 
 | |
|     if (pickedTime != null) {
 | |
|       final selectedDateTime = DateTime(
 | |
|         checkInTime.year,
 | |
|         checkInTime.month,
 | |
|         checkInTime.day,
 | |
|         pickedTime.hour,
 | |
|         pickedTime.minute,
 | |
|       );
 | |
| 
 | |
|       // Ensure selected time is after check-in time
 | |
|       if (selectedDateTime.isAfter(checkInTime)) {
 | |
|         return selectedDateTime;
 | |
|       } else {
 | |
|         ScaffoldMessenger.of(context).showSnackBar(
 | |
|           const SnackBar(
 | |
|               content: Text("Please select a time after check-in time.")),
 | |
|         );
 | |
|         return null;
 | |
|       }
 | |
|     }
 | |
|     return null;
 | |
|   }
 | |
| }
 |