refactor: enhance job attendance handling and improve null safety in models
This commit is contained in:
parent
919310644d
commit
2260382990
@ -34,7 +34,7 @@ class ServiceProjectDetailsController extends GetxController {
|
||||
// Inside ServiceProjectDetailsController
|
||||
var isTagging = false.obs;
|
||||
var attendanceMessage = ''.obs;
|
||||
var attendanceLog = Rxn<JobAttendanceResponse>();
|
||||
var attendanceLog = Rxn<JobAttendanceResponse>();
|
||||
|
||||
// -------------------- Lifecycle --------------------
|
||||
@override
|
||||
@ -91,10 +91,11 @@ var attendanceLog = Rxn<JobAttendanceResponse>();
|
||||
try {
|
||||
final result =
|
||||
await ApiService.getJobAttendanceLog(attendanceId: attendanceId);
|
||||
|
||||
if (result != null) {
|
||||
attendanceLog.value = result;
|
||||
} else {
|
||||
attendanceMessage.value = "Failed to fetch attendance log";
|
||||
attendanceMessage.value = "Attendance log not found or empty";
|
||||
}
|
||||
} catch (e) {
|
||||
attendanceMessage.value = "Error fetching attendance log: $e";
|
||||
|
||||
@ -39,7 +39,8 @@ class JobData {
|
||||
final String dueDate;
|
||||
final bool isActive;
|
||||
final dynamic taggingAction;
|
||||
final int nextTaggingAction;
|
||||
final String? attendanceId;
|
||||
final int? nextTaggingAction;
|
||||
final String createdAt;
|
||||
final User createdBy;
|
||||
final List<Tag> tags;
|
||||
@ -57,7 +58,8 @@ class JobData {
|
||||
required this.dueDate,
|
||||
required this.isActive,
|
||||
this.taggingAction,
|
||||
required this.nextTaggingAction,
|
||||
this.attendanceId,
|
||||
this.nextTaggingAction,
|
||||
required this.createdAt,
|
||||
required this.createdBy,
|
||||
required this.tags,
|
||||
@ -71,22 +73,27 @@ class JobData {
|
||||
description: json['description'] as String,
|
||||
jobTicketUId: json['jobTicketUId'] as String,
|
||||
project: Project.fromJson(json['project']),
|
||||
assignees: (json['assignees'] as List<dynamic>)
|
||||
.map((e) => Assignee.fromJson(e))
|
||||
.toList(),
|
||||
assignees: (json['assignees'] as List<dynamic>?)
|
||||
?.map((e) => Assignee.fromJson(e))
|
||||
.toList() ??
|
||||
[],
|
||||
status: Status.fromJson(json['status']),
|
||||
startDate: json['startDate'] as String,
|
||||
dueDate: json['dueDate'] as String,
|
||||
isActive: json['isActive'] as bool,
|
||||
taggingAction: json['taggingAction'],
|
||||
nextTaggingAction: json['nextTaggingAction'] as int,
|
||||
attendanceId: json['attendanceId'] as String?,
|
||||
nextTaggingAction: json['nextTaggingAction'] as int?,
|
||||
createdAt: json['createdAt'] as String,
|
||||
createdBy: User.fromJson(json['createdBy']),
|
||||
tags:
|
||||
(json['tags'] as List<dynamic>).map((e) => Tag.fromJson(e)).toList(),
|
||||
updateLogs: (json['updateLogs'] as List<dynamic>)
|
||||
.map((e) => UpdateLog.fromJson(e))
|
||||
.toList(),
|
||||
tags: (json['tags'] as List<dynamic>?)
|
||||
?.map((e) => Tag.fromJson(e))
|
||||
.toList() ??
|
||||
[],
|
||||
updateLogs: (json['updateLogs'] as List<dynamic>?)
|
||||
?.map((e) => UpdateLog.fromJson(e))
|
||||
.toList() ??
|
||||
[],
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -127,8 +134,8 @@ class Assignee {
|
||||
final String id;
|
||||
final String firstName;
|
||||
final String lastName;
|
||||
final String email;
|
||||
final String photo;
|
||||
final String? email;
|
||||
final String? photo;
|
||||
final String jobRoleId;
|
||||
final String jobRoleName;
|
||||
|
||||
@ -136,8 +143,8 @@ class Assignee {
|
||||
required this.id,
|
||||
required this.firstName,
|
||||
required this.lastName,
|
||||
required this.email,
|
||||
required this.photo,
|
||||
this.email,
|
||||
this.photo,
|
||||
required this.jobRoleId,
|
||||
required this.jobRoleName,
|
||||
});
|
||||
@ -147,8 +154,8 @@ class Assignee {
|
||||
id: json['id'] as String,
|
||||
firstName: json['firstName'] as String,
|
||||
lastName: json['lastName'] as String,
|
||||
email: json['email'] as String,
|
||||
photo: json['photo'] as String,
|
||||
email: json['email'] as String?,
|
||||
photo: json['photo'] as String?,
|
||||
jobRoleId: json['jobRoleId'] as String,
|
||||
jobRoleName: json['jobRoleName'] as String,
|
||||
);
|
||||
@ -182,8 +189,8 @@ class User {
|
||||
final String id;
|
||||
final String firstName;
|
||||
final String lastName;
|
||||
final String email;
|
||||
final String photo;
|
||||
final String? email;
|
||||
final String? photo;
|
||||
final String jobRoleId;
|
||||
final String jobRoleName;
|
||||
|
||||
@ -191,8 +198,8 @@ class User {
|
||||
required this.id,
|
||||
required this.firstName,
|
||||
required this.lastName,
|
||||
required this.email,
|
||||
required this.photo,
|
||||
this.email,
|
||||
this.photo,
|
||||
required this.jobRoleId,
|
||||
required this.jobRoleName,
|
||||
});
|
||||
@ -202,8 +209,8 @@ class User {
|
||||
id: json['id'] as String,
|
||||
firstName: json['firstName'] as String,
|
||||
lastName: json['lastName'] as String,
|
||||
email: json['email'] as String,
|
||||
photo: json['photo'] as String,
|
||||
email: json['email'] as String?,
|
||||
photo: json['photo'] as String?,
|
||||
jobRoleId: json['jobRoleId'] as String,
|
||||
jobRoleName: json['jobRoleName'] as String,
|
||||
);
|
||||
@ -211,18 +218,15 @@ class User {
|
||||
}
|
||||
|
||||
class Tag {
|
||||
final String id;
|
||||
final String name;
|
||||
final String? id;
|
||||
final String? name;
|
||||
|
||||
Tag({
|
||||
required this.id,
|
||||
required this.name,
|
||||
});
|
||||
Tag({this.id, this.name});
|
||||
|
||||
factory Tag.fromJson(Map<String, dynamic> json) {
|
||||
return Tag(
|
||||
id: json['id'] as String,
|
||||
name: json['name'] as String,
|
||||
id: json['id'] as String?,
|
||||
name: json['name'] as String?,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -351,7 +351,7 @@ class _ServiceProjectDetailsScreenState
|
||||
final job = controller.jobList[index];
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
Get.to(() => JobDetailsScreen(jobId: job.id));
|
||||
Get.to(() => JobDetailsScreen(jobId: job.id ));
|
||||
},
|
||||
child: Card(
|
||||
elevation: 3,
|
||||
|
||||
@ -199,7 +199,7 @@ class _JobDetailsScreenState extends State<JobDetailsScreen> with UIMixin {
|
||||
// Step 3: Perform attendance using controller
|
||||
await controller.updateJobAttendance(
|
||||
jobId: job.id,
|
||||
action: action,
|
||||
action: action == 0 ? 0 : 1,
|
||||
comment: comment ?? "",
|
||||
attachment: attachmentFile,
|
||||
);
|
||||
@ -342,7 +342,7 @@ class _JobDetailsScreenState extends State<JobDetailsScreen> with UIMixin {
|
||||
designation: a.jobRoleName,
|
||||
jobRole: a.jobRoleName,
|
||||
jobRoleID: a.jobRoleId,
|
||||
email: a.email,
|
||||
email: a.email ?? '',
|
||||
phoneNumber: '',
|
||||
activity: 0,
|
||||
action: 0,
|
||||
@ -405,7 +405,7 @@ class _JobDetailsScreenState extends State<JobDetailsScreen> with UIMixin {
|
||||
children: tags
|
||||
.map(
|
||||
(t) => Chip(
|
||||
label: Text(t.name),
|
||||
label: Text(t.name ?? ''),
|
||||
onDeleted: editing
|
||||
? () {
|
||||
_selectedTags.remove(t);
|
||||
@ -477,7 +477,7 @@ class _JobDetailsScreenState extends State<JobDetailsScreen> with UIMixin {
|
||||
isExpanded.value = !isExpanded.value;
|
||||
// Fetch attendance logs only when expanded
|
||||
if (isExpanded.value && job != null) {
|
||||
await controller.fetchJobAttendanceLog(job.jobTicketUId);
|
||||
await controller.fetchJobAttendanceLog(job.attendanceId ?? '');
|
||||
}
|
||||
},
|
||||
)),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user