This commit is contained in:
Phuoc Nguyen
2025-11-27 14:59:48 +07:00
parent dc8e60f589
commit ba04576750
25 changed files with 931 additions and 721 deletions

View File

@@ -1,129 +1,105 @@
import 'dart:convert';
/// Project Submission Model
///
/// Data model for project submission from API responses with Hive caching.
/// Based on API response from building_material.building_material.api.project.get_list
library;
import 'package:hive_ce/hive.dart';
import 'package:worker/core/constants/storage_constants.dart';
import 'package:worker/core/database/models/enums.dart';
import 'package:worker/features/projects/domain/entities/project_submission.dart';
part 'project_submission_model.g.dart';
/// Project Submission Model - Type ID: 14
@HiveType(typeId: HiveTypeIds.projectSubmissionModel)
class ProjectSubmissionModel extends HiveObject {
ProjectSubmissionModel({
required this.submissionId,
required this.userId,
required this.projectName,
required this.projectAddress,
required this.projectValue,
required this.projectType,
this.beforePhotos,
this.afterPhotos,
this.invoices,
required this.status,
this.reviewNotes,
this.rejectionReason,
this.pointsEarned,
required this.submittedAt,
this.reviewedAt,
this.reviewedBy,
});
/// Unique submission identifier (API: name)
@HiveField(0)
final String submissionId;
/// Project name/title (API: designed_area)
@HiveField(1)
final String userId;
final String designedArea;
/// Design area value in square meters (API: design_area)
@HiveField(2)
final String projectName;
final double designArea;
/// Submission/request date (API: request_date)
@HiveField(3)
final String projectAddress;
final DateTime requestDate;
/// Status label - Vietnamese (API: status)
@HiveField(4)
final double projectValue;
final String status;
/// Rejection reason if rejected (API: reason_for_rejection)
@HiveField(5)
final ProjectType projectType;
final String? reasonForRejection;
/// Status color indicator (API: status_color)
@HiveField(6)
final String? beforePhotos;
@HiveField(7)
final String? afterPhotos;
@HiveField(8)
final String? invoices;
@HiveField(9)
final SubmissionStatus status;
@HiveField(10)
final String? reviewNotes;
@HiveField(11)
final String? rejectionReason;
@HiveField(12)
final int? pointsEarned;
@HiveField(13)
final DateTime submittedAt;
@HiveField(14)
final DateTime? reviewedAt;
@HiveField(15)
final String? reviewedBy;
final String statusColor;
factory ProjectSubmissionModel.fromJson(
Map<String, dynamic> json,
) => ProjectSubmissionModel(
submissionId: json['submission_id'] as String,
userId: json['user_id'] as String,
projectName: json['project_name'] as String,
projectAddress: json['project_address'] as String,
projectValue: (json['project_value'] as num).toDouble(),
projectType: ProjectType.values.firstWhere(
(e) => e.name == json['project_type'],
),
beforePhotos: json['before_photos'] != null
? jsonEncode(json['before_photos'])
: null,
afterPhotos: json['after_photos'] != null
? jsonEncode(json['after_photos'])
: null,
invoices: json['invoices'] != null ? jsonEncode(json['invoices']) : null,
status: SubmissionStatus.values.firstWhere((e) => e.name == json['status']),
reviewNotes: json['review_notes'] as String?,
rejectionReason: json['rejection_reason'] as String?,
pointsEarned: json['points_earned'] as int?,
submittedAt: DateTime.parse(json['submitted_at']?.toString() ?? ''),
reviewedAt: json['reviewed_at'] != null
? DateTime.parse(json['reviewed_at']?.toString() ?? '')
: null,
reviewedBy: json['reviewed_by'] as String?,
);
ProjectSubmissionModel({
required this.submissionId,
required this.designedArea,
required this.designArea,
required this.requestDate,
required this.status,
this.reasonForRejection,
required this.statusColor,
});
Map<String, dynamic> toJson() => {
'submission_id': submissionId,
'user_id': userId,
'project_name': projectName,
'project_address': projectAddress,
'project_value': projectValue,
'project_type': projectType.name,
'before_photos': beforePhotos != null ? jsonDecode(beforePhotos!) : null,
'after_photos': afterPhotos != null ? jsonDecode(afterPhotos!) : null,
'invoices': invoices != null ? jsonDecode(invoices!) : null,
'status': status.name,
'review_notes': reviewNotes,
'rejection_reason': rejectionReason,
'points_earned': pointsEarned,
'submitted_at': submittedAt.toIso8601String(),
'reviewed_at': reviewedAt?.toIso8601String(),
'reviewed_by': reviewedBy,
};
List<String>? get beforePhotosList {
if (beforePhotos == null) return null;
try {
final decoded = jsonDecode(beforePhotos!) as List;
return decoded.map((e) => e.toString()).toList();
} catch (e) {
return null;
}
/// Create from JSON (API response)
factory ProjectSubmissionModel.fromJson(Map<String, dynamic> json) {
return ProjectSubmissionModel(
submissionId: json['name'] as String,
designedArea: json['designed_area'] as String,
designArea: (json['design_area'] as num).toDouble(),
requestDate: DateTime.parse(json['request_date'] as String),
status: json['status'] as String,
reasonForRejection: json['reason_for_rejection'] as String?,
statusColor: json['status_color'] as String,
);
}
List<String>? get afterPhotosList {
if (afterPhotos == null) return null;
try {
final decoded = jsonDecode(afterPhotos!) as List;
return decoded.map((e) => e.toString()).toList();
} catch (e) {
return null;
}
/// Convert to JSON
Map<String, dynamic> toJson() {
return {
'name': submissionId,
'designed_area': designedArea,
'design_area': designArea,
'request_date': requestDate.toIso8601String(),
'status': status,
'reason_for_rejection': reasonForRejection,
'status_color': statusColor,
};
}
/// Convert to entity
ProjectSubmission toEntity() {
return ProjectSubmission(
submissionId: submissionId,
designedArea: designedArea,
designArea: designArea,
requestDate: requestDate,
status: status,
reasonForRejection: reasonForRejection,
statusColor: statusColor,
);
}
/// Create from entity
factory ProjectSubmissionModel.fromEntity(ProjectSubmission entity) {
return ProjectSubmissionModel(
submissionId: entity.submissionId,
designedArea: entity.designedArea,
designArea: entity.designArea,
requestDate: entity.requestDate,
status: entity.status,
reasonForRejection: entity.reasonForRejection,
statusColor: entity.statusColor,
);
}
}