marco.pms.mobileapp/lib/view/Attendence/attendance_logs_tab.dart
Vaibhav Surve f5d4ab8415 feat: Add attendance log screen and related functionalities
- Implemented AttendenceLogScreen to display employee attendance logs.
- Created RegularizationRequestsTab to manage regularization requests.
- Added TodaysAttendanceTab for viewing today's attendance.
- Removed outdated dashboard chart implementation.
- Updated dashboard screen to integrate new attendance overview and project progress charts.
- Refactored employee detail and employee screens to use updated controllers.
- Organized expense-related imports and components for better structure.
- Adjusted daily progress report to use the correct controller.
2025-08-29 15:53:19 +05:30

189 lines
8.4 KiB
Dart

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:marco/controller/attendance/attendance_screen_controller.dart';
import 'package:marco/helpers/utils/date_time_utils.dart';
import 'package:marco/helpers/widgets/avatar.dart';
import 'package:marco/helpers/widgets/my_card.dart';
import 'package:marco/helpers/widgets/my_container.dart';
import 'package:marco/helpers/widgets/my_spacing.dart';
import 'package:marco/helpers/widgets/my_text.dart';
import 'package:marco/helpers/widgets/my_custom_skeleton.dart';
import 'package:marco/model/attendance/log_details_view.dart';
import 'package:marco/model/attendance/attendence_action_button.dart';
class AttendanceLogsTab extends StatelessWidget {
final AttendanceController controller;
const AttendanceLogsTab({super.key, required this.controller});
@override
Widget build(BuildContext context) {
return Obx(() {
final logs = List.of(controller.attendanceLogs);
logs.sort((a, b) {
final aDate = a.checkIn ?? DateTime(0);
final bDate = b.checkIn ?? DateTime(0);
return bDate.compareTo(aDate);
});
final dateRangeText = controller.startDateAttendance != null &&
controller.endDateAttendance != null
? '${DateTimeUtils.formatDate(controller.startDateAttendance!, 'dd MMM yyyy')} - '
'${DateTimeUtils.formatDate(controller.endDateAttendance!, 'dd MMM yyyy')}'
: 'Select date range';
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 8),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
MyText.titleMedium("Attendance Logs", fontWeight: 600),
controller.isLoading.value
? SkeletonLoaders.dateSkeletonLoader()
: MyText.bodySmall(
dateRangeText,
fontWeight: 600,
color: Colors.grey[700],
overflow: TextOverflow.ellipsis,
),
],
),
),
if (controller.isLoadingAttendanceLogs.value)
SkeletonLoaders.employeeListSkeletonLoader()
else if (logs.isEmpty)
const SizedBox(
height: 120,
child: Center(
child: Text("No Attendance Logs Found for this Project"),
),
)
else
MyCard.bordered(
paddingAll: 8,
child: Column(
children: List.generate(logs.length, (index) {
final employee = logs[index];
final currentDate = employee.checkIn != null
? DateTimeUtils.formatDate(
employee.checkIn!, 'dd MMM yyyy')
: '';
final previousDate =
index > 0 && logs[index - 1].checkIn != null
? DateTimeUtils.formatDate(
logs[index - 1].checkIn!, 'dd MMM yyyy')
: '';
final showDateHeader =
index == 0 || currentDate != previousDate;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (showDateHeader)
Padding(
padding: const EdgeInsets.symmetric(vertical: 8),
child: MyText.bodyMedium(
currentDate,
fontWeight: 700,
),
),
MyContainer(
paddingAll: 8,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Avatar(
firstName: employee.firstName,
lastName: employee.lastName,
size: 31,
),
MySpacing.width(16),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Flexible(
child: MyText.bodyMedium(
employee.name,
fontWeight: 600,
overflow: TextOverflow.ellipsis,
),
),
MySpacing.width(6),
Flexible(
child: MyText.bodySmall(
'(${employee.designation})',
fontWeight: 600,
color: Colors.grey[700],
overflow: TextOverflow.ellipsis,
),
),
],
),
MySpacing.height(8),
if (employee.checkIn != null ||
employee.checkOut != null)
Row(
children: [
if (employee.checkIn != null) ...[
const Icon(Icons.arrow_circle_right,
size: 16, color: Colors.green),
MySpacing.width(4),
MyText.bodySmall(
DateTimeUtils.formatDate(
employee.checkIn!, 'hh:mm a'),
fontWeight: 600,
),
MySpacing.width(16),
],
if (employee.checkOut != null) ...[
const Icon(Icons.arrow_circle_left,
size: 16, color: Colors.red),
MySpacing.width(4),
MyText.bodySmall(
DateTimeUtils.formatDate(
employee.checkOut!, 'hh:mm a'),
fontWeight: 600,
),
],
],
),
MySpacing.height(12),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
AttendanceActionButton(
employee: employee,
attendanceController: controller,
),
MySpacing.width(8),
AttendanceLogViewButton(
employee: employee,
attendanceController: controller,
),
],
),
],
),
),
],
),
),
if (index != logs.length - 1)
Divider(color: Colors.grey.withOpacity(0.3)),
],
);
}),
),
),
],
);
});
}
}