feat: Refactor project selection handling in attendance actions and controllers

This commit is contained in:
Vaibhav Surve 2025-06-12 23:18:58 +05:30
parent a97fb1f541
commit 59e6634023
4 changed files with 66 additions and 68 deletions

View File

@ -15,6 +15,7 @@ import 'package:marco/model/employee_model.dart';
import 'package:marco/model/attendance_log_model.dart';
import 'package:marco/model/regularization_log_model.dart';
import 'package:marco/model/attendance_log_view_model.dart';
import 'package:marco/controller/project_controller.dart';
final Logger log = Logger();
@ -28,7 +29,6 @@ class AttendanceController extends GetxController {
List<AttendanceLogViewModel> attendenceLogsView = [];
// Selected values
String? selectedProjectId;
String selectedTab = 'Employee List';
// Date range for attendance filtering
@ -279,7 +279,7 @@ class AttendanceController extends GetxController {
log.i("Date range selected: $startDateAttendance to $endDateAttendance");
await controller.fetchAttendanceLogs(
controller.selectedProjectId,
Get.find<ProjectController>().selectedProject?.id,
dateFrom: picked.start,
dateTo: picked.end,
);

View File

@ -4,6 +4,7 @@ import 'package:intl/intl.dart';
import 'package:marco/helpers/widgets/my_snackbar.dart';
import 'package:marco/controller/dashboard/attendance_screen_controller.dart';
import 'package:marco/helpers/utils/attendance_actions.dart';
import 'package:marco/controller/project_controller.dart';
class AttendanceActionButton extends StatefulWidget {
final dynamic employee;
@ -19,10 +20,11 @@ class AttendanceActionButton extends StatefulWidget {
State<AttendanceActionButton> createState() => _AttendanceActionButtonState();
}
Future<String?> _showCommentBottomSheet(BuildContext context, String actionText) async {
Future<String?> _showCommentBottomSheet(
BuildContext context, String actionText) async {
final TextEditingController commentController = TextEditingController();
String? errorText;
Get.find<ProjectController>().selectedProject?.id;
return showModalBottomSheet<String>(
context: context,
isScrollControlled: true,
@ -80,7 +82,7 @@ Future<String?> _showCommentBottomSheet(BuildContext context, String actionText)
),
const SizedBox(width: 12),
Expanded(
child: ElevatedButton(
child: ElevatedButton(
onPressed: () {
final comment = commentController.text.trim();
if (comment.isEmpty) {
@ -105,7 +107,6 @@ Future<String?> _showCommentBottomSheet(BuildContext context, String actionText)
);
}
String capitalizeFirstLetter(String text) {
if (text.isEmpty) return text;
return text[0].toUpperCase() + text.substring(1);
@ -163,7 +164,10 @@ class _AttendanceActionButtonState extends State<AttendanceActionButton> {
void _handleButtonPressed(BuildContext context) async {
widget.attendanceController.uploadingStates[uniqueLogKey]?.value = true;
if (widget.attendanceController.selectedProjectId == null) {
final projectController = Get.find<ProjectController>();
final selectedProjectId = projectController.selectedProject?.id;
if (selectedProjectId == null) {
showAppSnackbar(
title: "Project Required",
message: "Please select a project first",
@ -231,7 +235,7 @@ class _AttendanceActionButtonState extends State<AttendanceActionButton> {
success = await widget.attendanceController.captureAndUploadAttendance(
widget.employee.id,
widget.employee.employeeId,
widget.attendanceController.selectedProjectId!,
selectedProjectId,
comment: userComment,
action: updatedAction,
imageCapture: imageCapture,
@ -242,7 +246,7 @@ class _AttendanceActionButtonState extends State<AttendanceActionButton> {
success = await widget.attendanceController.captureAndUploadAttendance(
widget.employee.id,
widget.employee.employeeId,
widget.attendanceController.selectedProjectId!,
selectedProjectId,
comment: userComment,
action: updatedAction,
imageCapture: imageCapture,
@ -260,14 +264,11 @@ class _AttendanceActionButtonState extends State<AttendanceActionButton> {
widget.attendanceController.uploadingStates[uniqueLogKey]?.value = false;
if (success) {
widget.attendanceController.fetchEmployeesByProject(
widget.attendanceController.selectedProjectId!);
widget.attendanceController
.fetchAttendanceLogs(widget.attendanceController.selectedProjectId!);
await widget.attendanceController.fetchRegularizationLogs(
widget.attendanceController.selectedProjectId!);
widget.attendanceController.fetchEmployeesByProject(selectedProjectId);
widget.attendanceController.fetchAttendanceLogs(selectedProjectId);
await widget.attendanceController
.fetchProjectData(widget.attendanceController.selectedProjectId!);
.fetchRegularizationLogs(selectedProjectId);
await widget.attendanceController.fetchProjectData(selectedProjectId);
widget.attendanceController.update();
}
}

View File

@ -1,6 +1,8 @@
import 'package:flutter/material.dart';
import 'package:marco/helpers/utils/attendance_actions.dart';
import 'package:marco/helpers/widgets/my_snackbar.dart';
import 'package:marco/controller/project_controller.dart';
import 'package:get/get.dart';
enum ButtonActions { approve, reject }
class RegularizeActionButton extends StatefulWidget {
@ -51,60 +53,57 @@ class _RegularizeActionButtonState extends State<RegularizeActionButton> {
Colors.grey;
}
Future<void> _handlePress() async {
if (widget.attendanceController.selectedProjectId == null) {
showAppSnackbar(
title: 'Warning',
message: 'Please select a project first',
type: SnackbarType.warning,
);
return;
}
setState(() {
isUploading = true;
});
widget.attendanceController.uploadingStates[widget.uniqueLogKey]?.value =
true;
final success =
await widget.attendanceController.captureAndUploadAttendance(
widget.log.id,
widget.log.employeeId,
widget.attendanceController.selectedProjectId!,
comment: _buttonComments[widget.action]!,
action: _buttonActionCodes[widget.action]!,
imageCapture: false,
);
Future<void> _handlePress() async {
final projectController = Get.find<ProjectController>();
final selectedProjectId = projectController.selectedProject?.id;
if (selectedProjectId == null) {
showAppSnackbar(
title: success ? 'Success' : 'Error',
message: success
? '${capitalizeFirstLetter(_buttonTexts[widget.action]!)} marked successfully!'
: 'Failed to mark ${capitalizeFirstLetter(_buttonTexts[widget.action]!)}.',
type: success ? SnackbarType.success : SnackbarType.error,
title: 'Warning',
message: 'Please select a project first',
type: SnackbarType.warning,
);
if (success) {
widget.attendanceController.fetchEmployeesByProject(
widget.attendanceController.selectedProjectId!);
widget.attendanceController
.fetchAttendanceLogs(widget.attendanceController.selectedProjectId!);
await widget.attendanceController.fetchRegularizationLogs(
widget.attendanceController.selectedProjectId!);
await widget.attendanceController
.fetchProjectData(widget.attendanceController.selectedProjectId!);
}
widget.attendanceController.uploadingStates[widget.uniqueLogKey]?.value =
false;
setState(() {
isUploading = false;
});
return;
}
setState(() {
isUploading = true;
});
widget.attendanceController.uploadingStates[widget.uniqueLogKey]?.value = true;
final success = await widget.attendanceController.captureAndUploadAttendance(
widget.log.id,
widget.log.employeeId,
selectedProjectId,
comment: _buttonComments[widget.action]!,
action: _buttonActionCodes[widget.action]!,
imageCapture: false,
);
showAppSnackbar(
title: success ? 'Success' : 'Error',
message: success
? '${capitalizeFirstLetter(_buttonTexts[widget.action]!)} marked successfully!'
: 'Failed to mark ${capitalizeFirstLetter(_buttonTexts[widget.action]!)}.',
type: success ? SnackbarType.success : SnackbarType.error,
);
if (success) {
widget.attendanceController.fetchEmployeesByProject(selectedProjectId);
widget.attendanceController.fetchAttendanceLogs(selectedProjectId);
await widget.attendanceController.fetchRegularizationLogs(selectedProjectId);
await widget.attendanceController.fetchProjectData(selectedProjectId);
}
widget.attendanceController.uploadingStates[widget.uniqueLogKey]?.value = false;
setState(() {
isUploading = false;
});
}
@override
Widget build(BuildContext context) {
final buttonText = _buttonTexts[widget.action]!;

View File

@ -78,7 +78,7 @@ class _AttendanceScreenState extends State<AttendanceScreen> with UIMixin {
titleSpacing: 0,
centerTitle: false,
leading: Padding(
padding: const EdgeInsets.only(top: 15.0), // Aligns with title
padding: const EdgeInsets.only(top: 15.0),
child: IconButton(
icon: const Icon(Icons.arrow_back_ios_new,
color: Colors.black, size: 20),
@ -127,10 +127,8 @@ class _AttendanceScreenState extends State<AttendanceScreen> with UIMixin {
builder: (controller) {
final selectedProjectId =
Get.find<ProjectController>().selectedProjectId?.value;
final bool noProjectSelected =
selectedProjectId == null || selectedProjectId.isEmpty;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [