import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:on_field_work/controller/attendance/attendance_screen_controller.dart'; import 'package:on_field_work/helpers/utils/date_time_utils.dart'; import 'package:on_field_work/helpers/widgets/avatar.dart'; import 'package:on_field_work/helpers/widgets/my_container.dart'; import 'package:on_field_work/helpers/widgets/my_spacing.dart'; import 'package:on_field_work/helpers/widgets/my_text.dart'; import 'package:on_field_work/helpers/widgets/my_custom_skeleton.dart'; import 'package:on_field_work/model/attendance/log_details_view.dart'; import 'package:on_field_work/model/attendance/attendence_action_button.dart'; import 'package:on_field_work/helpers/utils/attendance_actions.dart'; class AttendanceLogsTab extends StatelessWidget { final AttendanceController controller; const AttendanceLogsTab({super.key, required this.controller}); Widget _buildStatusHeader() { return Obx(() { if (!controller.showPendingOnly.value) return const SizedBox.shrink(); return Container( width: double.infinity, padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16), color: Colors.orange.shade50, child: Row( children: [ const Icon(Icons.pending_actions, color: Colors.orange, size: 18), const SizedBox(width: 8), const Expanded( child: Text( "Showing Pending Actions Only", style: TextStyle( color: Colors.orange, fontWeight: FontWeight.w600, ), ), ), InkWell( onTap: () => controller.showPendingOnly.value = false, child: const Icon(Icons.close, size: 18, color: Colors.orange), ), ], ), ); }); } int _getActionPriority(employee) { final text = AttendanceButtonHelper.getButtonText( activity: employee.activity, checkIn: employee.checkIn, checkOut: employee.checkOut, isTodayApproved: AttendanceButtonHelper.isTodayApproved( employee.activity, employee.checkIn, ), ).toLowerCase(); final isYesterdayCheckIn = employee.checkIn != null && DateUtils.isSameDay( employee.checkIn, DateTime.now().subtract(const Duration(days: 1)), ); final isMissingCheckout = employee.checkOut == null; final isCheckoutAction = text.contains("checkout") || text.contains("check out"); if (isYesterdayCheckIn && isMissingCheckout && isCheckoutAction) return 0; if (isCheckoutAction) return 0; if (text.contains("regular")) return 1; if (text == "requested") return 2; if (text == "approved") return 3; if (text == "rejected") return 4; return 5; } @override Widget build(BuildContext context) { return Obx(() { final allLogs = List.of(controller.filteredLogs); final showPendingOnly = controller.showPendingOnly.value; final filteredLogs = showPendingOnly ? allLogs.where((emp) => emp.activity == 1).toList() : allLogs; // Group logs by date string final groupedLogs = >{}; for (var log in filteredLogs) { final dateKey = log.checkIn != null ? DateTimeUtils.formatDate(log.checkIn!, 'dd MMM yyyy') : 'Unknown'; groupedLogs.putIfAbsent(dateKey, () => []).add(log); } final sortedDates = groupedLogs.keys.toList() ..sort((a, b) { final da = DateTimeUtils.parseDate(a, 'dd MMM yyyy') ?? DateTime(0); final db = DateTimeUtils.parseDate(b, 'dd MMM yyyy') ?? DateTime(0); return db.compareTo(da); }); final dateRangeText = '${DateTimeUtils.formatDate(controller.startDateAttendance.value, 'dd MMM yyyy')} - ' '${DateTimeUtils.formatDate(controller.endDateAttendance.value, 'dd MMM yyyy')}'; // Sticky header + scrollable list return Column( children: [ // Header Row Padding( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 8), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ controller.isLoadingAttendanceLogs.value ? SkeletonLoaders.dateSkeletonLoader() : MyText.bodySmall( dateRangeText, fontWeight: 600, color: Colors.grey[700], overflow: TextOverflow.ellipsis, ), ], ), ), // Pending-only header _buildStatusHeader(), // Divider between header and list const Divider(height: 1), // Scrollable attendance logs Expanded( child: controller.isLoadingAttendanceLogs.value ? SkeletonLoaders.employeeListSkeletonLoader() : filteredLogs.isEmpty ? Center( child: Text(showPendingOnly ? "No Pending Actions Found" : "No Attendance Logs Found for this Project"), ) : ListView.builder( padding: MySpacing.all(8), itemCount: sortedDates.length, itemBuilder: (context, dateIndex) { final date = sortedDates[dateIndex]; final employees = groupedLogs[date]! ..sort((a, b) { final priorityCompare = _getActionPriority(a) .compareTo(_getActionPriority(b)); if (priorityCompare != 0) return priorityCompare; final aTime = a.checkOut ?? a.checkIn ?? DateTime(0); final bTime = b.checkOut ?? b.checkIn ?? DateTime(0); return bTime.compareTo(aTime); }); return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: const EdgeInsets.symmetric(vertical: 8), child: MyText.bodyMedium(date, fontWeight: 700), ), ...employees.map( (emp) => Column( children: [ MyContainer( paddingAll: 8, child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Avatar( firstName: emp.firstName, lastName: emp.lastName, size: 31, ), MySpacing.width(16), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Flexible( child: MyText.bodyMedium( emp.name, fontWeight: 600, overflow: TextOverflow .ellipsis, ), ), MySpacing.width(6), Flexible( child: MyText.bodySmall( '(${emp.designation})', fontWeight: 600, color: Colors.grey[700], overflow: TextOverflow .ellipsis, ), ), ], ), MySpacing.height(8), if (emp.checkIn != null || emp.checkOut != null) Row( children: [ if (emp.checkIn != null) ...[ const Icon( Icons .arrow_circle_right, size: 16, color: Colors.green), MySpacing.width(4), MyText.bodySmall( DateTimeUtils .formatDate( emp.checkIn!, 'hh:mm a'), fontWeight: 600, ), MySpacing.width(16), ], if (emp.checkOut != null) ...[ const Icon( Icons .arrow_circle_left, size: 16, color: Colors.red), MySpacing.width(4), MyText.bodySmall( DateTimeUtils .formatDate( emp.checkOut!, 'hh:mm a'), fontWeight: 600, ), ], ], ), MySpacing.height(12), Row( mainAxisAlignment: MainAxisAlignment.end, children: [ AttendanceActionButton( employee: emp, attendanceController: controller, ), MySpacing.width(8), AttendanceLogViewButton( employee: emp, attendanceController: controller, ), ], ), ], ), ), ], ), ), ], ), ), ], ); }, ), ), ], ); }); } }