/// Domain Entity: Project Submission /// /// Represents a completed project submitted for loyalty points. library; /// Project type enum enum ProjectType { /// Residential project residential, /// Commercial project commercial, /// Industrial project industrial, /// Public infrastructure infrastructure, /// Other type other; /// Get display name for project type String get displayName { switch (this) { case ProjectType.residential: return 'Residential'; case ProjectType.commercial: return 'Commercial'; case ProjectType.industrial: return 'Industrial'; case ProjectType.infrastructure: return 'Infrastructure'; case ProjectType.other: return 'Other'; } } } /// Submission status enum enum SubmissionStatus { /// Submitted, pending review pending, /// Under review reviewing, /// Approved, points awarded approved, /// Rejected rejected; /// Get display name for status String get displayName { switch (this) { case SubmissionStatus.pending: return 'Pending'; case SubmissionStatus.reviewing: return 'Reviewing'; case SubmissionStatus.approved: return 'Approved'; case SubmissionStatus.rejected: return 'Rejected'; } } } /// Project Submission Entity /// /// Contains information about a completed project: /// - Project details /// - Before/after photos /// - Invoice documentation /// - Review status /// - Points earned class ProjectSubmission { /// Unique submission identifier final String submissionId; /// User ID who submitted final String userId; /// Project name final String projectName; /// Project address/location final String? projectAddress; /// Project value/cost final double projectValue; /// Project type final ProjectType projectType; /// Before photos URLs final List beforePhotos; /// After photos URLs final List afterPhotos; /// Invoice/receipt URLs final List invoices; /// Submission status final SubmissionStatus status; /// Review notes from admin final String? reviewNotes; /// Rejection reason (if rejected) final String? rejectionReason; /// Points earned (if approved) final int? pointsEarned; /// Submission timestamp final DateTime submittedAt; /// Review timestamp final DateTime? reviewedAt; /// ID of admin who reviewed final String? reviewedBy; const ProjectSubmission({ required this.submissionId, required this.userId, required this.projectName, this.projectAddress, required this.projectValue, required this.projectType, required this.beforePhotos, required this.afterPhotos, required this.invoices, required this.status, this.reviewNotes, this.rejectionReason, this.pointsEarned, required this.submittedAt, this.reviewedAt, this.reviewedBy, }); /// Check if submission is pending bool get isPending => status == SubmissionStatus.pending; /// Check if submission is under review bool get isReviewing => status == SubmissionStatus.reviewing; /// Check if submission is approved bool get isApproved => status == SubmissionStatus.approved; /// Check if submission is rejected bool get isRejected => status == SubmissionStatus.rejected; /// Check if submission has been reviewed bool get isReviewed => status == SubmissionStatus.approved || status == SubmissionStatus.rejected; /// Check if submission has before photos bool get hasBeforePhotos => beforePhotos.isNotEmpty; /// Check if submission has after photos bool get hasAfterPhotos => afterPhotos.isNotEmpty; /// Check if submission has invoices bool get hasInvoices => invoices.isNotEmpty; /// Get total number of photos int get totalPhotos => beforePhotos.length + afterPhotos.length; /// Get review duration Duration? get reviewDuration { if (reviewedAt == null) return null; return reviewedAt!.difference(submittedAt); } /// Copy with method for immutability ProjectSubmission copyWith({ String? submissionId, String? userId, String? projectName, String? projectAddress, double? projectValue, ProjectType? projectType, List? beforePhotos, List? afterPhotos, List? invoices, SubmissionStatus? status, String? reviewNotes, String? rejectionReason, int? pointsEarned, DateTime? submittedAt, DateTime? reviewedAt, String? reviewedBy, }) { return ProjectSubmission( submissionId: submissionId ?? this.submissionId, userId: userId ?? this.userId, projectName: projectName ?? this.projectName, projectAddress: projectAddress ?? this.projectAddress, projectValue: projectValue ?? this.projectValue, projectType: projectType ?? this.projectType, beforePhotos: beforePhotos ?? this.beforePhotos, afterPhotos: afterPhotos ?? this.afterPhotos, invoices: invoices ?? this.invoices, status: status ?? this.status, reviewNotes: reviewNotes ?? this.reviewNotes, rejectionReason: rejectionReason ?? this.rejectionReason, pointsEarned: pointsEarned ?? this.pointsEarned, submittedAt: submittedAt ?? this.submittedAt, reviewedAt: reviewedAt ?? this.reviewedAt, reviewedBy: reviewedBy ?? this.reviewedBy, ); } @override bool operator ==(Object other) { if (identical(this, other)) return true; return other is ProjectSubmission && other.submissionId == submissionId && other.userId == userId && other.projectName == projectName && other.projectValue == projectValue && other.status == status; } @override int get hashCode { return Object.hash(submissionId, userId, projectName, projectValue, status); } @override String toString() { return 'ProjectSubmission(submissionId: $submissionId, projectName: $projectName, ' 'projectValue: $projectValue, projectType: $projectType, status: $status, ' 'pointsEarned: $pointsEarned)'; } }