/// Project Submission Model /// /// Data model for project submission from API responses. /// Based on API response from building_material.building_material.api.project.get_detail library; import 'package:worker/features/projects/domain/entities/project_submission.dart'; /// Project File Model class ProjectFileModel { /// Unique file identifier (API: name) final String id; /// Full URL to the file (API: file_url) final String fileUrl; const ProjectFileModel({ required this.id, required this.fileUrl, }); /// Create from JSON (API response) factory ProjectFileModel.fromJson(Map json) { return ProjectFileModel( id: json['name'] as String, fileUrl: json['file_url'] as String, ); } /// Convert to JSON Map toJson() { return { 'name': id, 'file_url': fileUrl, }; } /// Convert to entity ProjectFile toEntity() { return ProjectFile( id: id, fileUrl: fileUrl, ); } /// Create from entity factory ProjectFileModel.fromEntity(ProjectFile entity) { return ProjectFileModel( id: entity.id, fileUrl: entity.fileUrl, ); } } /// Project Submission Model class ProjectSubmissionModel { /// Unique submission identifier (API: name) final String submissionId; /// Project name/title (API: designed_area) final String designedArea; /// Design area value in square meters (API: design_area) final double designArea; /// Submission/request date (API: request_date) final DateTime requestDate; /// Status label - Vietnamese (API: status) final String status; /// Rejection reason if rejected (API: reason_for_rejection) final String? reasonForRejection; /// Status color indicator (API: status_color) final String statusColor; /// Project address (API: address_of_project) final String? addressOfProject; /// Project owner name (API: project_owner) final String? projectOwner; /// Design firm name (API: design_firm) final String? designFirm; /// Construction contractor name (API: contruction_contractor) final String? constructionContractor; /// Products included in the design (API: products_included_in_the_design) final String? productsIncludedInTheDesign; /// Project progress ID reference (API: project_progress) final String? projectProgress; /// Expected commencement date (API: expected_commencement_date) final DateTime? expectedCommencementDate; /// Project description (API: description) final String? description; /// Workflow state (API: workflow_state) final String? workflowState; /// Whether the submission can be modified (API: is_allow_modify) final bool isAllowModify; /// Whether the submission can be cancelled (API: is_allow_cancel) final bool isAllowCancel; /// List of attached files (API: files_list) final List filesList; const ProjectSubmissionModel({ required this.submissionId, required this.designedArea, required this.designArea, required this.requestDate, required this.status, this.reasonForRejection, required this.statusColor, this.addressOfProject, this.projectOwner, this.designFirm, this.constructionContractor, this.productsIncludedInTheDesign, this.projectProgress, this.expectedCommencementDate, this.description, this.workflowState, this.isAllowModify = false, this.isAllowCancel = false, this.filesList = const [], }); /// Create from JSON (API response) /// Handles both list response and detail response formats factory ProjectSubmissionModel.fromJson(Map json) { // Parse expected_commencement_date DateTime? expectedDate; final expectedDateStr = json['expected_commencement_date'] as String?; if (expectedDateStr != null && expectedDateStr.isNotEmpty) { try { expectedDate = DateTime.parse(expectedDateStr); } catch (_) {} } // Parse files_list final filesListJson = json['files_list'] as List?; final filesList = filesListJson ?.map((f) => ProjectFileModel.fromJson(f as Map)) .toList() ?? []; 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, addressOfProject: json['address_of_project'] as String?, projectOwner: json['project_owner'] as String?, designFirm: json['design_firm'] as String?, constructionContractor: json['contruction_contractor'] as String?, productsIncludedInTheDesign: json['products_included_in_the_design'] as String?, projectProgress: json['project_progress'] as String?, expectedCommencementDate: expectedDate, description: json['description'] as String?, workflowState: json['workflow_state'] as String?, isAllowModify: json['is_allow_modify'] as bool? ?? false, isAllowCancel: json['is_allow_cancel'] as bool? ?? false, filesList: filesList, ); } /// Convert to JSON Map toJson() { return { 'name': submissionId, 'designed_area': designedArea, 'design_area': designArea, 'request_date': requestDate.toIso8601String(), 'status': status, 'reason_for_rejection': reasonForRejection, 'status_color': statusColor, 'address_of_project': addressOfProject, 'project_owner': projectOwner, 'design_firm': designFirm, 'contruction_contractor': constructionContractor, 'products_included_in_the_design': productsIncludedInTheDesign, 'project_progress': projectProgress, 'expected_commencement_date': expectedCommencementDate?.toIso8601String(), 'description': description, 'workflow_state': workflowState, 'is_allow_modify': isAllowModify, 'is_allow_cancel': isAllowCancel, 'files_list': filesList.map((f) => f.toJson()).toList(), }; } /// Convert to entity ProjectSubmission toEntity() { return ProjectSubmission( submissionId: submissionId, designedArea: designedArea, designArea: designArea, requestDate: requestDate, status: status, reasonForRejection: reasonForRejection, statusColor: statusColor, addressOfProject: addressOfProject, projectOwner: projectOwner, designFirm: designFirm, constructionContractor: constructionContractor, productsIncludedInTheDesign: productsIncludedInTheDesign, projectProgress: projectProgress, expectedCommencementDate: expectedCommencementDate, description: description, workflowState: workflowState, isAllowModify: isAllowModify, isAllowCancel: isAllowCancel, filesList: filesList.map((f) => f.toEntity()).toList(), ); } /// 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, addressOfProject: entity.addressOfProject, projectOwner: entity.projectOwner, designFirm: entity.designFirm, constructionContractor: entity.constructionContractor, productsIncludedInTheDesign: entity.productsIncludedInTheDesign, projectProgress: entity.projectProgress, expectedCommencementDate: entity.expectedCommencementDate, description: entity.description, workflowState: entity.workflowState, isAllowModify: entity.isAllowModify, isAllowCancel: entity.isAllowCancel, filesList: entity.filesList.map((f) => ProjectFileModel.fromEntity(f)).toList(), ); } }